1686cdd19SJun-ichiro itojun Hagino /* $FreeBSD$ */ 233841545SHajimu UMEMOTO /* $KAME: scope6.c,v 1.10 2000/07/24 13:29:31 itojun Exp $ */ 3686cdd19SJun-ichiro itojun Hagino 4686cdd19SJun-ichiro itojun Hagino /* 5686cdd19SJun-ichiro itojun Hagino * Copyright (C) 2000 WIDE Project. 6686cdd19SJun-ichiro itojun Hagino * All rights reserved. 7686cdd19SJun-ichiro itojun Hagino * 8686cdd19SJun-ichiro itojun Hagino * Redistribution and use in source and binary forms, with or without 9686cdd19SJun-ichiro itojun Hagino * modification, are permitted provided that the following conditions 10686cdd19SJun-ichiro itojun Hagino * are met: 11686cdd19SJun-ichiro itojun Hagino * 1. Redistributions of source code must retain the above copyright 12686cdd19SJun-ichiro itojun Hagino * notice, this list of conditions and the following disclaimer. 13686cdd19SJun-ichiro itojun Hagino * 2. Redistributions in binary form must reproduce the above copyright 14686cdd19SJun-ichiro itojun Hagino * notice, this list of conditions and the following disclaimer in the 15686cdd19SJun-ichiro itojun Hagino * documentation and/or other materials provided with the distribution. 16686cdd19SJun-ichiro itojun Hagino * 3. Neither the name of the project nor the names of its contributors 17686cdd19SJun-ichiro itojun Hagino * may be used to endorse or promote products derived from this software 18686cdd19SJun-ichiro itojun Hagino * without specific prior written permission. 19686cdd19SJun-ichiro itojun Hagino * 20686cdd19SJun-ichiro itojun Hagino * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND 21686cdd19SJun-ichiro itojun Hagino * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 22686cdd19SJun-ichiro itojun Hagino * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 23686cdd19SJun-ichiro itojun Hagino * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE 24686cdd19SJun-ichiro itojun Hagino * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 25686cdd19SJun-ichiro itojun Hagino * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 26686cdd19SJun-ichiro itojun Hagino * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 27686cdd19SJun-ichiro itojun Hagino * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 28686cdd19SJun-ichiro itojun Hagino * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 29686cdd19SJun-ichiro itojun Hagino * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 30686cdd19SJun-ichiro itojun Hagino * SUCH DAMAGE. 31686cdd19SJun-ichiro itojun Hagino */ 32686cdd19SJun-ichiro itojun Hagino 33686cdd19SJun-ichiro itojun Hagino #include <sys/param.h> 34686cdd19SJun-ichiro itojun Hagino #include <sys/malloc.h> 35686cdd19SJun-ichiro itojun Hagino #include <sys/mbuf.h> 36686cdd19SJun-ichiro itojun Hagino #include <sys/socket.h> 37686cdd19SJun-ichiro itojun Hagino #include <sys/systm.h> 3833841545SHajimu UMEMOTO #include <sys/queue.h> 39686cdd19SJun-ichiro itojun Hagino 40686cdd19SJun-ichiro itojun Hagino #include <net/route.h> 41686cdd19SJun-ichiro itojun Hagino #include <net/if.h> 42686cdd19SJun-ichiro itojun Hagino 43686cdd19SJun-ichiro itojun Hagino #include <netinet/in.h> 44686cdd19SJun-ichiro itojun Hagino 45686cdd19SJun-ichiro itojun Hagino #include <netinet6/in6_var.h> 46686cdd19SJun-ichiro itojun Hagino #include <netinet6/scope6_var.h> 47686cdd19SJun-ichiro itojun Hagino 4831b1bfe1SHajimu UMEMOTO static struct scope6_id sid_default; 4931b1bfe1SHajimu UMEMOTO #define SID(ifp) \ 5031b1bfe1SHajimu UMEMOTO (((struct in6_ifextra *)(ifp)->if_afdata[AF_INET6])->scope6_id) 51686cdd19SJun-ichiro itojun Hagino 52686cdd19SJun-ichiro itojun Hagino void 5331b1bfe1SHajimu UMEMOTO scope6_init() 5431b1bfe1SHajimu UMEMOTO { 5531b1bfe1SHajimu UMEMOTO 5631b1bfe1SHajimu UMEMOTO bzero(&sid_default, sizeof(sid_default)); 5731b1bfe1SHajimu UMEMOTO } 5831b1bfe1SHajimu UMEMOTO 5931b1bfe1SHajimu UMEMOTO struct scope6_id * 60686cdd19SJun-ichiro itojun Hagino scope6_ifattach(ifp) 61686cdd19SJun-ichiro itojun Hagino struct ifnet *ifp; 62686cdd19SJun-ichiro itojun Hagino { 63686cdd19SJun-ichiro itojun Hagino int s = splnet(); 6431b1bfe1SHajimu UMEMOTO struct scope6_id *sid; 65686cdd19SJun-ichiro itojun Hagino 6631b1bfe1SHajimu UMEMOTO sid = (struct scope6_id *)malloc(sizeof(*sid), M_IFADDR, M_WAITOK); 6731b1bfe1SHajimu UMEMOTO bzero(sid, sizeof(*sid)); 68686cdd19SJun-ichiro itojun Hagino 69686cdd19SJun-ichiro itojun Hagino /* 70686cdd19SJun-ichiro itojun Hagino * XXX: IPV6_ADDR_SCOPE_xxx macros are not standard. 71686cdd19SJun-ichiro itojun Hagino * Should we rather hardcode here? 72686cdd19SJun-ichiro itojun Hagino */ 7331b1bfe1SHajimu UMEMOTO sid->s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = ifp->if_index; 7431b1bfe1SHajimu UMEMOTO sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = ifp->if_index; 75686cdd19SJun-ichiro itojun Hagino #ifdef MULTI_SCOPE 76686cdd19SJun-ichiro itojun Hagino /* by default, we don't care about scope boundary for these scopes. */ 7731b1bfe1SHajimu UMEMOTO sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL] = 1; 7831b1bfe1SHajimu UMEMOTO sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL] = 1; 79686cdd19SJun-ichiro itojun Hagino #endif 80686cdd19SJun-ichiro itojun Hagino 81686cdd19SJun-ichiro itojun Hagino splx(s); 8231b1bfe1SHajimu UMEMOTO return sid; 8331b1bfe1SHajimu UMEMOTO } 8431b1bfe1SHajimu UMEMOTO 8531b1bfe1SHajimu UMEMOTO void 8631b1bfe1SHajimu UMEMOTO scope6_ifdetach(sid) 8731b1bfe1SHajimu UMEMOTO struct scope6_id *sid; 8831b1bfe1SHajimu UMEMOTO { 8931b1bfe1SHajimu UMEMOTO 9031b1bfe1SHajimu UMEMOTO free(sid, M_IFADDR); 91686cdd19SJun-ichiro itojun Hagino } 92686cdd19SJun-ichiro itojun Hagino 93686cdd19SJun-ichiro itojun Hagino int 94686cdd19SJun-ichiro itojun Hagino scope6_set(ifp, idlist) 95686cdd19SJun-ichiro itojun Hagino struct ifnet *ifp; 9631b1bfe1SHajimu UMEMOTO struct scope6_id *idlist; 97686cdd19SJun-ichiro itojun Hagino { 98686cdd19SJun-ichiro itojun Hagino int i, s; 99686cdd19SJun-ichiro itojun Hagino int error = 0; 10031b1bfe1SHajimu UMEMOTO struct scope6_id *sid = SID(ifp); 101686cdd19SJun-ichiro itojun Hagino 10231b1bfe1SHajimu UMEMOTO if (!sid) /* paranoid? */ 103686cdd19SJun-ichiro itojun Hagino return (EINVAL); 104686cdd19SJun-ichiro itojun Hagino 105686cdd19SJun-ichiro itojun Hagino /* 106686cdd19SJun-ichiro itojun Hagino * XXX: We need more consistency checks of the relationship among 107686cdd19SJun-ichiro itojun Hagino * scopes (e.g. an organization should be larger than a site). 108686cdd19SJun-ichiro itojun Hagino */ 109686cdd19SJun-ichiro itojun Hagino 110686cdd19SJun-ichiro itojun Hagino /* 111686cdd19SJun-ichiro itojun Hagino * TODO(XXX): after setting, we should reflect the changes to 112686cdd19SJun-ichiro itojun Hagino * interface addresses, routing table entries, PCB entries... 113686cdd19SJun-ichiro itojun Hagino */ 114686cdd19SJun-ichiro itojun Hagino 115686cdd19SJun-ichiro itojun Hagino s = splnet(); 116686cdd19SJun-ichiro itojun Hagino 117686cdd19SJun-ichiro itojun Hagino for (i = 0; i < 16; i++) { 11831b1bfe1SHajimu UMEMOTO if (idlist->s6id_list[i] && 11931b1bfe1SHajimu UMEMOTO idlist->s6id_list[i] != sid->s6id_list[i]) { 120686cdd19SJun-ichiro itojun Hagino if (i == IPV6_ADDR_SCOPE_LINKLOCAL && 12131b1bfe1SHajimu UMEMOTO idlist->s6id_list[i] > if_index) { 122686cdd19SJun-ichiro itojun Hagino /* 123686cdd19SJun-ichiro itojun Hagino * XXX: theoretically, there should be no 124686cdd19SJun-ichiro itojun Hagino * relationship between link IDs and interface 125686cdd19SJun-ichiro itojun Hagino * IDs, but we check the consistency for 126686cdd19SJun-ichiro itojun Hagino * safety in later use. 127686cdd19SJun-ichiro itojun Hagino */ 128686cdd19SJun-ichiro itojun Hagino splx(s); 129686cdd19SJun-ichiro itojun Hagino return (EINVAL); 130686cdd19SJun-ichiro itojun Hagino } 131686cdd19SJun-ichiro itojun Hagino 132686cdd19SJun-ichiro itojun Hagino /* 133686cdd19SJun-ichiro itojun Hagino * XXX: we must need lots of work in this case, 134686cdd19SJun-ichiro itojun Hagino * but we simply set the new value in this initial 135686cdd19SJun-ichiro itojun Hagino * implementation. 136686cdd19SJun-ichiro itojun Hagino */ 13731b1bfe1SHajimu UMEMOTO sid->s6id_list[i] = idlist->s6id_list[i]; 138686cdd19SJun-ichiro itojun Hagino } 139686cdd19SJun-ichiro itojun Hagino } 140686cdd19SJun-ichiro itojun Hagino splx(s); 141686cdd19SJun-ichiro itojun Hagino 142686cdd19SJun-ichiro itojun Hagino return (error); 143686cdd19SJun-ichiro itojun Hagino } 144686cdd19SJun-ichiro itojun Hagino 145686cdd19SJun-ichiro itojun Hagino int 146686cdd19SJun-ichiro itojun Hagino scope6_get(ifp, idlist) 147686cdd19SJun-ichiro itojun Hagino struct ifnet *ifp; 14831b1bfe1SHajimu UMEMOTO struct scope6_id *idlist; 149686cdd19SJun-ichiro itojun Hagino { 15031b1bfe1SHajimu UMEMOTO struct scope6_id *sid = SID(ifp); 15131b1bfe1SHajimu UMEMOTO 15231b1bfe1SHajimu UMEMOTO if (sid == NULL) /* paranoid? */ 153686cdd19SJun-ichiro itojun Hagino return (EINVAL); 154686cdd19SJun-ichiro itojun Hagino 15531b1bfe1SHajimu UMEMOTO *idlist = *sid; 156686cdd19SJun-ichiro itojun Hagino 157686cdd19SJun-ichiro itojun Hagino return (0); 158686cdd19SJun-ichiro itojun Hagino } 159686cdd19SJun-ichiro itojun Hagino 160686cdd19SJun-ichiro itojun Hagino 161686cdd19SJun-ichiro itojun Hagino /* 162686cdd19SJun-ichiro itojun Hagino * Get a scope of the address. Node-local, link-local, site-local or global. 163686cdd19SJun-ichiro itojun Hagino */ 164686cdd19SJun-ichiro itojun Hagino int 165686cdd19SJun-ichiro itojun Hagino in6_addrscope(addr) 166686cdd19SJun-ichiro itojun Hagino struct in6_addr *addr; 167686cdd19SJun-ichiro itojun Hagino { 168686cdd19SJun-ichiro itojun Hagino int scope; 169686cdd19SJun-ichiro itojun Hagino 170686cdd19SJun-ichiro itojun Hagino if (addr->s6_addr8[0] == 0xfe) { 171686cdd19SJun-ichiro itojun Hagino scope = addr->s6_addr8[1] & 0xc0; 172686cdd19SJun-ichiro itojun Hagino 173686cdd19SJun-ichiro itojun Hagino switch (scope) { 174686cdd19SJun-ichiro itojun Hagino case 0x80: 175686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_LINKLOCAL; 176686cdd19SJun-ichiro itojun Hagino break; 177686cdd19SJun-ichiro itojun Hagino case 0xc0: 178686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_SITELOCAL; 179686cdd19SJun-ichiro itojun Hagino break; 180686cdd19SJun-ichiro itojun Hagino default: 181686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_GLOBAL; /* just in case */ 182686cdd19SJun-ichiro itojun Hagino break; 183686cdd19SJun-ichiro itojun Hagino } 184686cdd19SJun-ichiro itojun Hagino } 185686cdd19SJun-ichiro itojun Hagino 186686cdd19SJun-ichiro itojun Hagino 187686cdd19SJun-ichiro itojun Hagino if (addr->s6_addr8[0] == 0xff) { 188686cdd19SJun-ichiro itojun Hagino scope = addr->s6_addr8[1] & 0x0f; 189686cdd19SJun-ichiro itojun Hagino 190686cdd19SJun-ichiro itojun Hagino /* 191686cdd19SJun-ichiro itojun Hagino * due to other scope such as reserved, 192686cdd19SJun-ichiro itojun Hagino * return scope doesn't work. 193686cdd19SJun-ichiro itojun Hagino */ 194686cdd19SJun-ichiro itojun Hagino switch (scope) { 195686cdd19SJun-ichiro itojun Hagino case IPV6_ADDR_SCOPE_NODELOCAL: 196686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_NODELOCAL; 197686cdd19SJun-ichiro itojun Hagino break; 198686cdd19SJun-ichiro itojun Hagino case IPV6_ADDR_SCOPE_LINKLOCAL: 199686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_LINKLOCAL; 200686cdd19SJun-ichiro itojun Hagino break; 201686cdd19SJun-ichiro itojun Hagino case IPV6_ADDR_SCOPE_SITELOCAL: 202686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_SITELOCAL; 203686cdd19SJun-ichiro itojun Hagino break; 204686cdd19SJun-ichiro itojun Hagino default: 205686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_GLOBAL; 206686cdd19SJun-ichiro itojun Hagino break; 207686cdd19SJun-ichiro itojun Hagino } 208686cdd19SJun-ichiro itojun Hagino } 209686cdd19SJun-ichiro itojun Hagino 210ddebd678SHajimu UMEMOTO if (bcmp(&in6addr_loopback, addr, sizeof(*addr) - 1) == 0) { 211686cdd19SJun-ichiro itojun Hagino if (addr->s6_addr8[15] == 1) /* loopback */ 212686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_NODELOCAL; 213686cdd19SJun-ichiro itojun Hagino if (addr->s6_addr8[15] == 0) /* unspecified */ 214686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_LINKLOCAL; 215686cdd19SJun-ichiro itojun Hagino } 216686cdd19SJun-ichiro itojun Hagino 217686cdd19SJun-ichiro itojun Hagino return IPV6_ADDR_SCOPE_GLOBAL; 218686cdd19SJun-ichiro itojun Hagino } 219686cdd19SJun-ichiro itojun Hagino 220686cdd19SJun-ichiro itojun Hagino int 221686cdd19SJun-ichiro itojun Hagino in6_addr2scopeid(ifp, addr) 222686cdd19SJun-ichiro itojun Hagino struct ifnet *ifp; /* must not be NULL */ 223686cdd19SJun-ichiro itojun Hagino struct in6_addr *addr; /* must not be NULL */ 224686cdd19SJun-ichiro itojun Hagino { 22531b1bfe1SHajimu UMEMOTO int scope; 22631b1bfe1SHajimu UMEMOTO struct scope6_id *sid = SID(ifp); 227686cdd19SJun-ichiro itojun Hagino 22831b1bfe1SHajimu UMEMOTO #ifdef DIAGNOSTIC 22931b1bfe1SHajimu UMEMOTO if (sid == NULL) { /* should not happen */ 23031b1bfe1SHajimu UMEMOTO panic("in6_addr2zoneid: scope array is NULL"); 23131b1bfe1SHajimu UMEMOTO /* NOTREACHED */ 23231b1bfe1SHajimu UMEMOTO } 23331b1bfe1SHajimu UMEMOTO #endif 234686cdd19SJun-ichiro itojun Hagino 23531b1bfe1SHajimu UMEMOTO /* 23631b1bfe1SHajimu UMEMOTO * special case: the loopback address can only belong to a loopback 23731b1bfe1SHajimu UMEMOTO * interface. 23831b1bfe1SHajimu UMEMOTO */ 23931b1bfe1SHajimu UMEMOTO if (IN6_IS_ADDR_LOOPBACK(addr)) { 24031b1bfe1SHajimu UMEMOTO if (!(ifp->if_flags & IFF_LOOPBACK)) 24131b1bfe1SHajimu UMEMOTO return (-1); 24231b1bfe1SHajimu UMEMOTO else 24331b1bfe1SHajimu UMEMOTO return (0); /* there's no ambiguity */ 24431b1bfe1SHajimu UMEMOTO } 24531b1bfe1SHajimu UMEMOTO 24631b1bfe1SHajimu UMEMOTO scope = in6_addrscope(addr); 24731b1bfe1SHajimu UMEMOTO 248686cdd19SJun-ichiro itojun Hagino switch(scope) { 249686cdd19SJun-ichiro itojun Hagino case IPV6_ADDR_SCOPE_NODELOCAL: 250686cdd19SJun-ichiro itojun Hagino return (-1); /* XXX: is this an appropriate value? */ 251686cdd19SJun-ichiro itojun Hagino 252686cdd19SJun-ichiro itojun Hagino case IPV6_ADDR_SCOPE_LINKLOCAL: 25331b1bfe1SHajimu UMEMOTO return (sid->s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL]); 254686cdd19SJun-ichiro itojun Hagino 255686cdd19SJun-ichiro itojun Hagino case IPV6_ADDR_SCOPE_SITELOCAL: 25631b1bfe1SHajimu UMEMOTO return (sid->s6id_list[IPV6_ADDR_SCOPE_SITELOCAL]); 257686cdd19SJun-ichiro itojun Hagino 258686cdd19SJun-ichiro itojun Hagino case IPV6_ADDR_SCOPE_ORGLOCAL: 25931b1bfe1SHajimu UMEMOTO return (sid->s6id_list[IPV6_ADDR_SCOPE_ORGLOCAL]); 260686cdd19SJun-ichiro itojun Hagino 261686cdd19SJun-ichiro itojun Hagino default: 262686cdd19SJun-ichiro itojun Hagino return (0); /* XXX: treat as global. */ 263686cdd19SJun-ichiro itojun Hagino } 264686cdd19SJun-ichiro itojun Hagino } 265686cdd19SJun-ichiro itojun Hagino 266686cdd19SJun-ichiro itojun Hagino void 267686cdd19SJun-ichiro itojun Hagino scope6_setdefault(ifp) 268686cdd19SJun-ichiro itojun Hagino struct ifnet *ifp; /* note that this might be NULL */ 269686cdd19SJun-ichiro itojun Hagino { 270686cdd19SJun-ichiro itojun Hagino /* 27131b1bfe1SHajimu UMEMOTO * Currently, this function just set the default "interfaces" 27231b1bfe1SHajimu UMEMOTO * and "links" according to the given interface. 273686cdd19SJun-ichiro itojun Hagino * We might eventually have to separate the notion of "link" from 274686cdd19SJun-ichiro itojun Hagino * "interface" and provide a user interface to set the default. 275686cdd19SJun-ichiro itojun Hagino */ 276686cdd19SJun-ichiro itojun Hagino if (ifp) { 27731b1bfe1SHajimu UMEMOTO sid_default.s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = 27831b1bfe1SHajimu UMEMOTO ifp->if_index; 27931b1bfe1SHajimu UMEMOTO sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 280686cdd19SJun-ichiro itojun Hagino ifp->if_index; 28107eb2995SHajimu UMEMOTO } else { 28231b1bfe1SHajimu UMEMOTO sid_default.s6id_list[IPV6_ADDR_SCOPE_NODELOCAL] = 0; 28331b1bfe1SHajimu UMEMOTO sid_default.s6id_list[IPV6_ADDR_SCOPE_LINKLOCAL] = 0; 284686cdd19SJun-ichiro itojun Hagino } 28507eb2995SHajimu UMEMOTO } 286686cdd19SJun-ichiro itojun Hagino 287686cdd19SJun-ichiro itojun Hagino int 288686cdd19SJun-ichiro itojun Hagino scope6_get_default(idlist) 28931b1bfe1SHajimu UMEMOTO struct scope6_id *idlist; 290686cdd19SJun-ichiro itojun Hagino { 29131b1bfe1SHajimu UMEMOTO *idlist = sid_default; 292686cdd19SJun-ichiro itojun Hagino 293686cdd19SJun-ichiro itojun Hagino return (0); 294686cdd19SJun-ichiro itojun Hagino } 295686cdd19SJun-ichiro itojun Hagino 296686cdd19SJun-ichiro itojun Hagino u_int32_t 297686cdd19SJun-ichiro itojun Hagino scope6_addr2default(addr) 298686cdd19SJun-ichiro itojun Hagino struct in6_addr *addr; 299686cdd19SJun-ichiro itojun Hagino { 30031b1bfe1SHajimu UMEMOTO /* 30131b1bfe1SHajimu UMEMOTO * special case: The loopback address should be considered as 30231b1bfe1SHajimu UMEMOTO * link-local, but there's no ambiguity in the syntax. 30331b1bfe1SHajimu UMEMOTO */ 30431b1bfe1SHajimu UMEMOTO if (IN6_IS_ADDR_LOOPBACK(addr)) 30531b1bfe1SHajimu UMEMOTO return (0); 30631b1bfe1SHajimu UMEMOTO 30731b1bfe1SHajimu UMEMOTO return (sid_default.s6id_list[in6_addrscope(addr)]); 308686cdd19SJun-ichiro itojun Hagino } 309