1/* $NetBSD: if_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $ */
| 1/* $NetBSD: if_arcsubr.c,v 1.36 2001/06/14 05:44:23 itojun Exp $ */
|
2/* $FreeBSD: head/sys/net/if_arcsubr.c 109771 2003-01-24 01:32:20Z fjoe $ */
| 2/* $FreeBSD: head/sys/net/if_arcsubr.c 110106 2003-01-30 15:55:02Z fjoe $ */
|
3 4/* 5 * Copyright (c) 1994, 1995 Ignatios Souvatzis 6 * Copyright (c) 1982, 1989, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: NetBSD: if_ethersubr.c,v 1.9 1994/06/29 06:36:11 cgd Exp 38 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 39 * 40 */ 41#include "opt_inet.h" 42#include "opt_inet6.h" 43#include "opt_ipx.h" 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/kernel.h> 48#include <sys/malloc.h> 49#include <sys/mbuf.h> 50#include <sys/protosw.h> 51#include <sys/socket.h> 52#include <sys/sockio.h> 53#include <sys/errno.h> 54#include <sys/syslog.h> 55 56#include <machine/cpu.h> 57 58#include <net/if.h> 59#include <net/netisr.h> 60#include <net/route.h> 61#include <net/if_dl.h> 62#include <net/if_types.h> 63#include <net/if_arc.h> 64#include <net/if_arp.h> 65#include <net/bpf.h> 66 67#if defined(INET) || defined(INET6) 68#include <netinet/in.h> 69#include <netinet/in_var.h> 70#include <netinet/if_ether.h> 71#endif 72 73#ifdef INET6 74#include <netinet6/nd6.h> 75#endif 76 77#ifdef IPX 78#include <netipx/ipx.h> 79#include <netipx/ipx_if.h> 80#endif 81 82MODULE_VERSION(arcnet, 1); 83 84#define ARCNET_ALLOW_BROKEN_ARP 85 86static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 87static int arc_resolvemulti(struct ifnet *, struct sockaddr **, 88 struct sockaddr *); 89 90u_int8_t arcbroadcastaddr = 0; 91
| 3 4/* 5 * Copyright (c) 1994, 1995 Ignatios Souvatzis 6 * Copyright (c) 1982, 1989, 1993 7 * The Regents of the University of California. All rights reserved. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * from: NetBSD: if_ethersubr.c,v 1.9 1994/06/29 06:36:11 cgd Exp 38 * @(#)if_ethersubr.c 8.1 (Berkeley) 6/10/93 39 * 40 */ 41#include "opt_inet.h" 42#include "opt_inet6.h" 43#include "opt_ipx.h" 44 45#include <sys/param.h> 46#include <sys/systm.h> 47#include <sys/kernel.h> 48#include <sys/malloc.h> 49#include <sys/mbuf.h> 50#include <sys/protosw.h> 51#include <sys/socket.h> 52#include <sys/sockio.h> 53#include <sys/errno.h> 54#include <sys/syslog.h> 55 56#include <machine/cpu.h> 57 58#include <net/if.h> 59#include <net/netisr.h> 60#include <net/route.h> 61#include <net/if_dl.h> 62#include <net/if_types.h> 63#include <net/if_arc.h> 64#include <net/if_arp.h> 65#include <net/bpf.h> 66 67#if defined(INET) || defined(INET6) 68#include <netinet/in.h> 69#include <netinet/in_var.h> 70#include <netinet/if_ether.h> 71#endif 72 73#ifdef INET6 74#include <netinet6/nd6.h> 75#endif 76 77#ifdef IPX 78#include <netipx/ipx.h> 79#include <netipx/ipx_if.h> 80#endif 81 82MODULE_VERSION(arcnet, 1); 83 84#define ARCNET_ALLOW_BROKEN_ARP 85 86static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 87static int arc_resolvemulti(struct ifnet *, struct sockaddr **, 88 struct sockaddr *); 89 90u_int8_t arcbroadcastaddr = 0; 91
|
| 92#define ARC_LLADDR(ifp) (*(u_int8_t *)IF_LLADDR(ifp)) 93
|
92#define senderr(e) { error = (e); goto bad;} 93#define SIN(s) ((struct sockaddr_in *)s) 94#define SIPX(s) ((struct sockaddr_ipx *)s) 95 96/* 97 * ARCnet output routine. 98 * Encapsulate a packet of type family for the local net. 99 * Assumes that ifp is actually pointer to arccom structure. 100 */ 101int 102arc_output(ifp, m, dst, rt0) 103 struct ifnet *ifp; 104 struct mbuf *m; 105 struct sockaddr *dst; 106 struct rtentry *rt0; 107{ 108 struct rtentry *rt; 109 struct arccom *ac; 110 struct arc_header *ah; 111 int error; 112 u_int8_t atype, adst; 113 int loop_copy = 0;
| 94#define senderr(e) { error = (e); goto bad;} 95#define SIN(s) ((struct sockaddr_in *)s) 96#define SIPX(s) ((struct sockaddr_ipx *)s) 97 98/* 99 * ARCnet output routine. 100 * Encapsulate a packet of type family for the local net. 101 * Assumes that ifp is actually pointer to arccom structure. 102 */ 103int 104arc_output(ifp, m, dst, rt0) 105 struct ifnet *ifp; 106 struct mbuf *m; 107 struct sockaddr *dst; 108 struct rtentry *rt0; 109{ 110 struct rtentry *rt; 111 struct arccom *ac; 112 struct arc_header *ah; 113 int error; 114 u_int8_t atype, adst; 115 int loop_copy = 0;
|
| 116 int isphds;
|
114 115 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 116 return(ENETDOWN); /* m, m1 aren't initialized yet */ 117 118 error = 0; 119 ac = (struct arccom *)ifp; 120 121 if ((rt = rt0)) { 122 if ((rt->rt_flags & RTF_UP) == 0) { 123 if ((rt0 = rt = rtalloc1(dst, 1, 0UL))) 124 rt->rt_refcnt--; 125 else 126 senderr(EHOSTUNREACH); 127 } 128 if (rt->rt_flags & RTF_GATEWAY) { 129 if (rt->rt_gwroute == 0) 130 goto lookup; 131 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 132 rtfree(rt); rt = rt0; 133 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL); 134 if ((rt = rt->rt_gwroute) == 0) 135 senderr(EHOSTUNREACH); 136 } 137 } 138 if (rt->rt_flags & RTF_REJECT) 139 if (rt->rt_rmx.rmx_expire == 0 || 140 time_second < rt->rt_rmx.rmx_expire) 141 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 142 } 143 144 switch (dst->sa_family) { 145#ifdef INET 146 case AF_INET: 147 148 /* 149 * For now, use the simple IP addr -> ARCnet addr mapping 150 */ 151 if (m->m_flags & (M_BCAST|M_MCAST)) 152 adst = arcbroadcastaddr; /* ARCnet broadcast address */ 153 else if (ifp->if_flags & IFF_NOARP) 154 adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 155 else if (!arpresolve(ifp, rt, m, dst, &adst, rt0)) 156 return 0; /* not resolved yet */ 157 158 atype = (ifp->if_flags & IFF_LINK0) ? 159 ARCTYPE_IP_OLD : ARCTYPE_IP; 160 break; 161#endif 162#ifdef INET6 163 case AF_INET6: 164#ifdef OLDIP6OUTPUT 165 if (!nd6_resolve(ifp, rt, m, dst, (u_char *)&adst)) 166 return(0); /* if not yet resolves */ 167#else 168 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)&adst)) 169 return(0); /* it must be impossible, but... */ 170#endif /* OLDIP6OUTPUT */ 171 atype = ARCTYPE_INET6; 172 break; 173#endif 174#ifdef IPX 175 case AF_IPX: 176 adst = SIPX(dst)->sipx_addr.x_host.c_host[5]; 177 atype = ARCTYPE_IPX; 178 if (adst == 0xff) 179 adst = arcbroadcastaddr; 180 break; 181#endif 182 183 case AF_UNSPEC: 184 loop_copy = -1; 185 ah = (struct arc_header *)dst->sa_data; 186 adst = ah->arc_dhost; 187 atype = ah->arc_type; 188 189 if (atype == ARCTYPE_ARP) { 190 atype = (ifp->if_flags & IFF_LINK0) ? 191 ARCTYPE_ARP_OLD: ARCTYPE_ARP; 192 193#ifdef ARCNET_ALLOW_BROKEN_ARP 194 /* 195 * XXX It's not clear per RFC826 if this is needed, but 196 * "assigned numbers" say this is wrong. 197 * However, e.g., AmiTCP 3.0Beta used it... we make this 198 * switchable for emergency cases. Not perfect, but... 199 */ 200 if (ifp->if_flags & IFF_LINK2) 201 mtod(m, struct arphdr *)->ar_pro = atype - 1; 202#endif 203 } 204 break; 205 206 default: 207 if_printf(ifp, "can't handle af%d\n", dst->sa_family); 208 senderr(EAFNOSUPPORT); 209 } 210
| 117 118 if ((ifp->if_flags & (IFF_UP|IFF_RUNNING)) != (IFF_UP|IFF_RUNNING)) 119 return(ENETDOWN); /* m, m1 aren't initialized yet */ 120 121 error = 0; 122 ac = (struct arccom *)ifp; 123 124 if ((rt = rt0)) { 125 if ((rt->rt_flags & RTF_UP) == 0) { 126 if ((rt0 = rt = rtalloc1(dst, 1, 0UL))) 127 rt->rt_refcnt--; 128 else 129 senderr(EHOSTUNREACH); 130 } 131 if (rt->rt_flags & RTF_GATEWAY) { 132 if (rt->rt_gwroute == 0) 133 goto lookup; 134 if (((rt = rt->rt_gwroute)->rt_flags & RTF_UP) == 0) { 135 rtfree(rt); rt = rt0; 136 lookup: rt->rt_gwroute = rtalloc1(rt->rt_gateway, 1, 0UL); 137 if ((rt = rt->rt_gwroute) == 0) 138 senderr(EHOSTUNREACH); 139 } 140 } 141 if (rt->rt_flags & RTF_REJECT) 142 if (rt->rt_rmx.rmx_expire == 0 || 143 time_second < rt->rt_rmx.rmx_expire) 144 senderr(rt == rt0 ? EHOSTDOWN : EHOSTUNREACH); 145 } 146 147 switch (dst->sa_family) { 148#ifdef INET 149 case AF_INET: 150 151 /* 152 * For now, use the simple IP addr -> ARCnet addr mapping 153 */ 154 if (m->m_flags & (M_BCAST|M_MCAST)) 155 adst = arcbroadcastaddr; /* ARCnet broadcast address */ 156 else if (ifp->if_flags & IFF_NOARP) 157 adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 158 else if (!arpresolve(ifp, rt, m, dst, &adst, rt0)) 159 return 0; /* not resolved yet */ 160 161 atype = (ifp->if_flags & IFF_LINK0) ? 162 ARCTYPE_IP_OLD : ARCTYPE_IP; 163 break; 164#endif 165#ifdef INET6 166 case AF_INET6: 167#ifdef OLDIP6OUTPUT 168 if (!nd6_resolve(ifp, rt, m, dst, (u_char *)&adst)) 169 return(0); /* if not yet resolves */ 170#else 171 if (!nd6_storelladdr(ifp, rt, m, dst, (u_char *)&adst)) 172 return(0); /* it must be impossible, but... */ 173#endif /* OLDIP6OUTPUT */ 174 atype = ARCTYPE_INET6; 175 break; 176#endif 177#ifdef IPX 178 case AF_IPX: 179 adst = SIPX(dst)->sipx_addr.x_host.c_host[5]; 180 atype = ARCTYPE_IPX; 181 if (adst == 0xff) 182 adst = arcbroadcastaddr; 183 break; 184#endif 185 186 case AF_UNSPEC: 187 loop_copy = -1; 188 ah = (struct arc_header *)dst->sa_data; 189 adst = ah->arc_dhost; 190 atype = ah->arc_type; 191 192 if (atype == ARCTYPE_ARP) { 193 atype = (ifp->if_flags & IFF_LINK0) ? 194 ARCTYPE_ARP_OLD: ARCTYPE_ARP; 195 196#ifdef ARCNET_ALLOW_BROKEN_ARP 197 /* 198 * XXX It's not clear per RFC826 if this is needed, but 199 * "assigned numbers" say this is wrong. 200 * However, e.g., AmiTCP 3.0Beta used it... we make this 201 * switchable for emergency cases. Not perfect, but... 202 */ 203 if (ifp->if_flags & IFF_LINK2) 204 mtod(m, struct arphdr *)->ar_pro = atype - 1; 205#endif 206 } 207 break; 208 209 default: 210 if_printf(ifp, "can't handle af%d\n", dst->sa_family); 211 senderr(EAFNOSUPPORT); 212 } 213
|
211 M_PREPEND(m, ARC_HDRLEN, M_NOWAIT);
| 214 isphds = arc_isphds(atype); 215 M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_NOWAIT);
|
212 if (m == 0) 213 senderr(ENOBUFS); 214 ah = mtod(m, struct arc_header *); 215 ah->arc_type = atype; 216 ah->arc_dhost = adst;
| 216 if (m == 0) 217 senderr(ENOBUFS); 218 ah = mtod(m, struct arc_header *); 219 ah->arc_type = atype; 220 ah->arc_dhost = adst;
|
217 ah->arc_shost = *IF_LLADDR(ifp);
| 221 ah->arc_shost = ARC_LLADDR(ifp); 222 if (isphds) { 223 ah->arc_flag = 0; 224 ah->arc_seqid = 0; 225 }
|
218 219 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 220 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 221 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 222 223 (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); 224 } else if (ah->arc_dhost == ah->arc_shost) { 225 (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); 226 return (0); /* XXX */ 227 } 228 } 229 230 BPF_MTAP(ifp, m); 231 232 if (!IF_HANDOFF(&ifp->if_snd, m, ifp)) { 233 m = 0; 234 senderr(ENOBUFS); 235 } 236 237 return (error); 238 239bad: 240 if (m) 241 m_freem(m); 242 return (error); 243} 244 245void 246arc_frag_init(ifp) 247 struct ifnet *ifp; 248{ 249 struct arccom *ac; 250 251 ac = (struct arccom *)ifp; 252 ac->curr_frag = 0; 253} 254 255struct mbuf * 256arc_frag_next(ifp) 257 struct ifnet *ifp; 258{ 259 struct arccom *ac; 260 struct mbuf *m; 261 struct arc_header *ah; 262 263 ac = (struct arccom *)ifp; 264 if ((m = ac->curr_frag) == 0) { 265 int tfrags; 266 267 /* dequeue new packet */ 268 IF_DEQUEUE(&ifp->if_snd, m); 269 if (m == 0) 270 return 0; 271 272 ah = mtod(m, struct arc_header *); 273 if (!arc_isphds(ah->arc_type)) 274 return m; 275 276 ++ac->ac_seqid; /* make the seqid unique */ 277 tfrags = (m->m_pkthdr.len + ARC_MAX_DATA - 1) / ARC_MAX_DATA; 278 ac->fsflag = 2 * tfrags - 3; 279 ac->sflag = 0; 280 ac->rsflag = ac->fsflag; 281 ac->arc_dhost = ah->arc_dhost; 282 ac->arc_shost = ah->arc_shost; 283 ac->arc_type = ah->arc_type; 284
| 226 227 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 228 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 229 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 230 231 (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); 232 } else if (ah->arc_dhost == ah->arc_shost) { 233 (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); 234 return (0); /* XXX */ 235 } 236 } 237 238 BPF_MTAP(ifp, m); 239 240 if (!IF_HANDOFF(&ifp->if_snd, m, ifp)) { 241 m = 0; 242 senderr(ENOBUFS); 243 } 244 245 return (error); 246 247bad: 248 if (m) 249 m_freem(m); 250 return (error); 251} 252 253void 254arc_frag_init(ifp) 255 struct ifnet *ifp; 256{ 257 struct arccom *ac; 258 259 ac = (struct arccom *)ifp; 260 ac->curr_frag = 0; 261} 262 263struct mbuf * 264arc_frag_next(ifp) 265 struct ifnet *ifp; 266{ 267 struct arccom *ac; 268 struct mbuf *m; 269 struct arc_header *ah; 270 271 ac = (struct arccom *)ifp; 272 if ((m = ac->curr_frag) == 0) { 273 int tfrags; 274 275 /* dequeue new packet */ 276 IF_DEQUEUE(&ifp->if_snd, m); 277 if (m == 0) 278 return 0; 279 280 ah = mtod(m, struct arc_header *); 281 if (!arc_isphds(ah->arc_type)) 282 return m; 283 284 ++ac->ac_seqid; /* make the seqid unique */ 285 tfrags = (m->m_pkthdr.len + ARC_MAX_DATA - 1) / ARC_MAX_DATA; 286 ac->fsflag = 2 * tfrags - 3; 287 ac->sflag = 0; 288 ac->rsflag = ac->fsflag; 289 ac->arc_dhost = ah->arc_dhost; 290 ac->arc_shost = ah->arc_shost; 291 ac->arc_type = ah->arc_type; 292
|
285 m_adj(m, ARC_HDRLEN);
| 293 m_adj(m, ARC_HDRNEWLEN);
|
286 ac->curr_frag = m; 287 } 288 289 /* split out next fragment and return it */ 290 if (ac->sflag < ac->fsflag) { 291 /* we CAN'T have short packets here */ 292 ac->curr_frag = m_split(m, ARC_MAX_DATA, M_NOWAIT); 293 if (ac->curr_frag == 0) { 294 m_freem(m); 295 return 0; 296 } 297 298 M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 299 if (m == 0) { 300 m_freem(ac->curr_frag); 301 ac->curr_frag = 0; 302 return 0; 303 } 304 305 ah = mtod(m, struct arc_header *); 306 ah->arc_flag = ac->rsflag; 307 ah->arc_seqid = ac->ac_seqid; 308 309 ac->sflag += 2; 310 ac->rsflag = ac->sflag; 311 } else if ((m->m_pkthdr.len >= 312 ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && 313 (m->m_pkthdr.len <= 314 ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { 315 ac->curr_frag = 0; 316 317 M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_NOWAIT); 318 if (m == 0) 319 return 0; 320 321 ah = mtod(m, struct arc_header *); 322 ah->arc_flag = 0xFF; 323 ah->arc_seqid = 0xFFFF; 324 ah->arc_type2 = ac->arc_type; 325 ah->arc_flag2 = ac->sflag; 326 ah->arc_seqid2 = ac->ac_seqid; 327 } else { 328 ac->curr_frag = 0; 329 330 M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 331 if (m == 0) 332 return 0; 333 334 ah = mtod(m, struct arc_header *); 335 ah->arc_flag = ac->sflag; 336 ah->arc_seqid = ac->ac_seqid; 337 } 338 339 ah->arc_dhost = ac->arc_dhost; 340 ah->arc_shost = ac->arc_shost; 341 ah->arc_type = ac->arc_type; 342 343 return m; 344} 345 346/* 347 * Defragmenter. Returns mbuf if last packet found, else 348 * NULL. frees imcoming mbuf as necessary. 349 */ 350 351static __inline struct mbuf * 352arc_defrag(ifp, m) 353 struct ifnet *ifp; 354 struct mbuf *m; 355{ 356 struct arc_header *ah, *ah1; 357 struct arccom *ac; 358 struct ac_frag *af; 359 struct mbuf *m1; 360 char *s; 361 int newflen; 362 u_char src,dst,typ; 363 364 ac = (struct arccom *)ifp; 365 366 if (m->m_len < ARC_HDRNEWLEN) { 367 m = m_pullup(m, ARC_HDRNEWLEN); 368 if (m == NULL) { 369 ++ifp->if_ierrors; 370 return NULL; 371 } 372 } 373 374 ah = mtod(m, struct arc_header *); 375 typ = ah->arc_type; 376 377 if (!arc_isphds(typ)) 378 return m; 379 380 src = ah->arc_shost; 381 dst = ah->arc_dhost; 382 383 if (ah->arc_flag == 0xff) { 384 m_adj(m, 4); 385 386 if (m->m_len < ARC_HDRNEWLEN) { 387 m = m_pullup(m, ARC_HDRNEWLEN); 388 if (m == NULL) { 389 ++ifp->if_ierrors; 390 return NULL; 391 } 392 } 393 394 ah = mtod(m, struct arc_header *); 395 } 396 397 af = &ac->ac_fragtab[src]; 398 m1 = af->af_packet; 399 s = "debug code error"; 400 401 if (ah->arc_flag & 1) { 402 /* 403 * first fragment. We always initialize, which is 404 * about the right thing to do, as we only want to 405 * accept one fragmented packet per src at a time. 406 */ 407 if (m1 != NULL) 408 m_freem(m1); 409 410 af->af_packet = m; 411 m1 = m; 412 af->af_maxflag = ah->arc_flag; 413 af->af_lastseen = 0; 414 af->af_seqid = ah->arc_seqid; 415 416 return NULL; 417 /* notreached */ 418 } else { 419 /* check for unfragmented packet */ 420 if (ah->arc_flag == 0) 421 return m; 422 423 /* do we have a first packet from that src? */ 424 if (m1 == NULL) { 425 s = "no first frag"; 426 goto outofseq; 427 } 428 429 ah1 = mtod(m1, struct arc_header *); 430 431 if (ah->arc_seqid != ah1->arc_seqid) { 432 s = "seqid differs"; 433 goto outofseq; 434 } 435 436 if (typ != ah1->arc_type) { 437 s = "type differs"; 438 goto outofseq; 439 } 440 441 if (dst != ah1->arc_dhost) { 442 s = "dest host differs"; 443 goto outofseq; 444 } 445 446 /* typ, seqid and dst are ok here. */ 447 448 if (ah->arc_flag == af->af_lastseen) { 449 m_freem(m); 450 return NULL; 451 } 452 453 if (ah->arc_flag == af->af_lastseen + 2) { 454 /* ok, this is next fragment */ 455 af->af_lastseen = ah->arc_flag; 456 m_adj(m,ARC_HDRNEWLEN); 457 458 /* 459 * m_cat might free the first mbuf (with pkthdr) 460 * in 2nd chain; therefore: 461 */ 462 463 newflen = m->m_pkthdr.len; 464 465 m_cat(m1,m); 466 467 m1->m_pkthdr.len += newflen; 468 469 /* is it the last one? */ 470 if (af->af_lastseen > af->af_maxflag) { 471 af->af_packet = NULL; 472 return(m1); 473 } else 474 return NULL; 475 } 476 s = "other reason"; 477 /* if all else fails, it is out of sequence, too */ 478 } 479outofseq: 480 if (m1) { 481 m_freem(m1); 482 af->af_packet = NULL; 483 } 484 485 if (m) 486 m_freem(m); 487 488 log(LOG_INFO,"%s%d: got out of seq. packet: %s\n", 489 ifp->if_name, ifp->if_unit, s); 490 491 return NULL; 492} 493 494/* 495 * return 1 if Packet Header Definition Standard, else 0. 496 * For now: old IP, old ARP aren't obviously. Lacking correct information, 497 * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 498 * (Apple and Novell corporations were involved, among others, in PHDS work). 499 * Easiest is to assume that everybody else uses that, too. 500 */ 501int 502arc_isphds(type) 503 u_int8_t type; 504{ 505 return (type != ARCTYPE_IP_OLD && 506 type != ARCTYPE_ARP_OLD && 507 type != ARCTYPE_DIAGNOSE); 508} 509 510/* 511 * Process a received Arcnet packet; 512 * the packet is in the mbuf chain m with 513 * the ARCnet header. 514 */ 515void 516arc_input(ifp, m) 517 struct ifnet *ifp; 518 struct mbuf *m; 519{ 520 struct arc_header *ah; 521 struct ifqueue *inq; 522 u_int8_t atype; 523 524 if ((ifp->if_flags & IFF_UP) == 0) { 525 m_freem(m); 526 return; 527 } 528 529 /* possibly defragment: */ 530 m = arc_defrag(ifp, m); 531 if (m == NULL) 532 return; 533 534 BPF_MTAP(ifp, m); 535 536 ah = mtod(m, struct arc_header *); 537 /* does this belong to us? */
| 294 ac->curr_frag = m; 295 } 296 297 /* split out next fragment and return it */ 298 if (ac->sflag < ac->fsflag) { 299 /* we CAN'T have short packets here */ 300 ac->curr_frag = m_split(m, ARC_MAX_DATA, M_NOWAIT); 301 if (ac->curr_frag == 0) { 302 m_freem(m); 303 return 0; 304 } 305 306 M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 307 if (m == 0) { 308 m_freem(ac->curr_frag); 309 ac->curr_frag = 0; 310 return 0; 311 } 312 313 ah = mtod(m, struct arc_header *); 314 ah->arc_flag = ac->rsflag; 315 ah->arc_seqid = ac->ac_seqid; 316 317 ac->sflag += 2; 318 ac->rsflag = ac->sflag; 319 } else if ((m->m_pkthdr.len >= 320 ARC_MIN_FORBID_LEN - ARC_HDRNEWLEN + 2) && 321 (m->m_pkthdr.len <= 322 ARC_MAX_FORBID_LEN - ARC_HDRNEWLEN + 2)) { 323 ac->curr_frag = 0; 324 325 M_PREPEND(m, ARC_HDRNEWLEN_EXC, M_NOWAIT); 326 if (m == 0) 327 return 0; 328 329 ah = mtod(m, struct arc_header *); 330 ah->arc_flag = 0xFF; 331 ah->arc_seqid = 0xFFFF; 332 ah->arc_type2 = ac->arc_type; 333 ah->arc_flag2 = ac->sflag; 334 ah->arc_seqid2 = ac->ac_seqid; 335 } else { 336 ac->curr_frag = 0; 337 338 M_PREPEND(m, ARC_HDRNEWLEN, M_NOWAIT); 339 if (m == 0) 340 return 0; 341 342 ah = mtod(m, struct arc_header *); 343 ah->arc_flag = ac->sflag; 344 ah->arc_seqid = ac->ac_seqid; 345 } 346 347 ah->arc_dhost = ac->arc_dhost; 348 ah->arc_shost = ac->arc_shost; 349 ah->arc_type = ac->arc_type; 350 351 return m; 352} 353 354/* 355 * Defragmenter. Returns mbuf if last packet found, else 356 * NULL. frees imcoming mbuf as necessary. 357 */ 358 359static __inline struct mbuf * 360arc_defrag(ifp, m) 361 struct ifnet *ifp; 362 struct mbuf *m; 363{ 364 struct arc_header *ah, *ah1; 365 struct arccom *ac; 366 struct ac_frag *af; 367 struct mbuf *m1; 368 char *s; 369 int newflen; 370 u_char src,dst,typ; 371 372 ac = (struct arccom *)ifp; 373 374 if (m->m_len < ARC_HDRNEWLEN) { 375 m = m_pullup(m, ARC_HDRNEWLEN); 376 if (m == NULL) { 377 ++ifp->if_ierrors; 378 return NULL; 379 } 380 } 381 382 ah = mtod(m, struct arc_header *); 383 typ = ah->arc_type; 384 385 if (!arc_isphds(typ)) 386 return m; 387 388 src = ah->arc_shost; 389 dst = ah->arc_dhost; 390 391 if (ah->arc_flag == 0xff) { 392 m_adj(m, 4); 393 394 if (m->m_len < ARC_HDRNEWLEN) { 395 m = m_pullup(m, ARC_HDRNEWLEN); 396 if (m == NULL) { 397 ++ifp->if_ierrors; 398 return NULL; 399 } 400 } 401 402 ah = mtod(m, struct arc_header *); 403 } 404 405 af = &ac->ac_fragtab[src]; 406 m1 = af->af_packet; 407 s = "debug code error"; 408 409 if (ah->arc_flag & 1) { 410 /* 411 * first fragment. We always initialize, which is 412 * about the right thing to do, as we only want to 413 * accept one fragmented packet per src at a time. 414 */ 415 if (m1 != NULL) 416 m_freem(m1); 417 418 af->af_packet = m; 419 m1 = m; 420 af->af_maxflag = ah->arc_flag; 421 af->af_lastseen = 0; 422 af->af_seqid = ah->arc_seqid; 423 424 return NULL; 425 /* notreached */ 426 } else { 427 /* check for unfragmented packet */ 428 if (ah->arc_flag == 0) 429 return m; 430 431 /* do we have a first packet from that src? */ 432 if (m1 == NULL) { 433 s = "no first frag"; 434 goto outofseq; 435 } 436 437 ah1 = mtod(m1, struct arc_header *); 438 439 if (ah->arc_seqid != ah1->arc_seqid) { 440 s = "seqid differs"; 441 goto outofseq; 442 } 443 444 if (typ != ah1->arc_type) { 445 s = "type differs"; 446 goto outofseq; 447 } 448 449 if (dst != ah1->arc_dhost) { 450 s = "dest host differs"; 451 goto outofseq; 452 } 453 454 /* typ, seqid and dst are ok here. */ 455 456 if (ah->arc_flag == af->af_lastseen) { 457 m_freem(m); 458 return NULL; 459 } 460 461 if (ah->arc_flag == af->af_lastseen + 2) { 462 /* ok, this is next fragment */ 463 af->af_lastseen = ah->arc_flag; 464 m_adj(m,ARC_HDRNEWLEN); 465 466 /* 467 * m_cat might free the first mbuf (with pkthdr) 468 * in 2nd chain; therefore: 469 */ 470 471 newflen = m->m_pkthdr.len; 472 473 m_cat(m1,m); 474 475 m1->m_pkthdr.len += newflen; 476 477 /* is it the last one? */ 478 if (af->af_lastseen > af->af_maxflag) { 479 af->af_packet = NULL; 480 return(m1); 481 } else 482 return NULL; 483 } 484 s = "other reason"; 485 /* if all else fails, it is out of sequence, too */ 486 } 487outofseq: 488 if (m1) { 489 m_freem(m1); 490 af->af_packet = NULL; 491 } 492 493 if (m) 494 m_freem(m); 495 496 log(LOG_INFO,"%s%d: got out of seq. packet: %s\n", 497 ifp->if_name, ifp->if_unit, s); 498 499 return NULL; 500} 501 502/* 503 * return 1 if Packet Header Definition Standard, else 0. 504 * For now: old IP, old ARP aren't obviously. Lacking correct information, 505 * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 506 * (Apple and Novell corporations were involved, among others, in PHDS work). 507 * Easiest is to assume that everybody else uses that, too. 508 */ 509int 510arc_isphds(type) 511 u_int8_t type; 512{ 513 return (type != ARCTYPE_IP_OLD && 514 type != ARCTYPE_ARP_OLD && 515 type != ARCTYPE_DIAGNOSE); 516} 517 518/* 519 * Process a received Arcnet packet; 520 * the packet is in the mbuf chain m with 521 * the ARCnet header. 522 */ 523void 524arc_input(ifp, m) 525 struct ifnet *ifp; 526 struct mbuf *m; 527{ 528 struct arc_header *ah; 529 struct ifqueue *inq; 530 u_int8_t atype; 531 532 if ((ifp->if_flags & IFF_UP) == 0) { 533 m_freem(m); 534 return; 535 } 536 537 /* possibly defragment: */ 538 m = arc_defrag(ifp, m); 539 if (m == NULL) 540 return; 541 542 BPF_MTAP(ifp, m); 543 544 ah = mtod(m, struct arc_header *); 545 /* does this belong to us? */
|
538 if ((ifp->if_flags & IFF_PROMISC) != 0
| 546 if ((ifp->if_flags & IFF_PROMISC) == 0
|
539 && ah->arc_dhost != arcbroadcastaddr
| 547 && ah->arc_dhost != arcbroadcastaddr
|
540 && ah->arc_dhost != *IF_LLADDR(ifp)) {
| 548 && ah->arc_dhost != ARC_LLADDR(ifp)) {
|
541 m_freem(m); 542 return; 543 } 544 545 ifp->if_ibytes += m->m_pkthdr.len; 546 547 if (ah->arc_dhost == arcbroadcastaddr) { 548 m->m_flags |= M_BCAST|M_MCAST; 549 ifp->if_imcasts++; 550 } 551 552 atype = ah->arc_type; 553 switch (atype) { 554#ifdef INET 555 case ARCTYPE_IP: 556 m_adj(m, ARC_HDRNEWLEN); 557 if (ipflow_fastforward(m)) 558 return; 559 schednetisr(NETISR_IP); 560 inq = &ipintrq; 561 break; 562 563 case ARCTYPE_IP_OLD: 564 m_adj(m, ARC_HDRLEN); 565 if (ipflow_fastforward(m)) 566 return; 567 schednetisr(NETISR_IP); 568 inq = &ipintrq; 569 break; 570 571 case ARCTYPE_ARP: 572 if (ifp->if_flags & IFF_NOARP) { 573 /* Discard packet if ARP is disabled on interface */ 574 m_freem(m); 575 return; 576 } 577 m_adj(m, ARC_HDRNEWLEN); 578 schednetisr(NETISR_ARP); 579 inq = &arpintrq; 580#ifdef ARCNET_ALLOW_BROKEN_ARP 581 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 582#endif 583 break; 584 585 case ARCTYPE_ARP_OLD: 586 if (ifp->if_flags & IFF_NOARP) { 587 /* Discard packet if ARP is disabled on interface */ 588 m_freem(m); 589 return; 590 } 591 m_adj(m, ARC_HDRLEN); 592 schednetisr(NETISR_ARP); 593 inq = &arpintrq; 594#ifdef ARCNET_ALLOW_BROKEN_ARP 595 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 596#endif 597 break; 598#endif 599#ifdef INET6 600 case ARCTYPE_INET6: 601 m_adj(m, ARC_HDRNEWLEN); 602 schednetisr(NETISR_IPV6); 603 inq = &ip6intrq; 604 break; 605#endif 606#ifdef IPX 607 case ARCTYPE_IPX: 608 m_adj(m, ARC_HDRNEWLEN); 609 schednetisr(NETISR_IPX); 610 inq = &ipxintrq; 611 break; 612#endif 613 default: 614 m_freem(m); 615 return; 616 } 617 618 IF_HANDOFF(inq, m, NULL); 619} 620 621/* 622 * Register (new) link level address. 623 */ 624void 625arc_storelladdr(ifp, lla) 626 struct ifnet *ifp; 627 u_int8_t lla; 628{
| 549 m_freem(m); 550 return; 551 } 552 553 ifp->if_ibytes += m->m_pkthdr.len; 554 555 if (ah->arc_dhost == arcbroadcastaddr) { 556 m->m_flags |= M_BCAST|M_MCAST; 557 ifp->if_imcasts++; 558 } 559 560 atype = ah->arc_type; 561 switch (atype) { 562#ifdef INET 563 case ARCTYPE_IP: 564 m_adj(m, ARC_HDRNEWLEN); 565 if (ipflow_fastforward(m)) 566 return; 567 schednetisr(NETISR_IP); 568 inq = &ipintrq; 569 break; 570 571 case ARCTYPE_IP_OLD: 572 m_adj(m, ARC_HDRLEN); 573 if (ipflow_fastforward(m)) 574 return; 575 schednetisr(NETISR_IP); 576 inq = &ipintrq; 577 break; 578 579 case ARCTYPE_ARP: 580 if (ifp->if_flags & IFF_NOARP) { 581 /* Discard packet if ARP is disabled on interface */ 582 m_freem(m); 583 return; 584 } 585 m_adj(m, ARC_HDRNEWLEN); 586 schednetisr(NETISR_ARP); 587 inq = &arpintrq; 588#ifdef ARCNET_ALLOW_BROKEN_ARP 589 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 590#endif 591 break; 592 593 case ARCTYPE_ARP_OLD: 594 if (ifp->if_flags & IFF_NOARP) { 595 /* Discard packet if ARP is disabled on interface */ 596 m_freem(m); 597 return; 598 } 599 m_adj(m, ARC_HDRLEN); 600 schednetisr(NETISR_ARP); 601 inq = &arpintrq; 602#ifdef ARCNET_ALLOW_BROKEN_ARP 603 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 604#endif 605 break; 606#endif 607#ifdef INET6 608 case ARCTYPE_INET6: 609 m_adj(m, ARC_HDRNEWLEN); 610 schednetisr(NETISR_IPV6); 611 inq = &ip6intrq; 612 break; 613#endif 614#ifdef IPX 615 case ARCTYPE_IPX: 616 m_adj(m, ARC_HDRNEWLEN); 617 schednetisr(NETISR_IPX); 618 inq = &ipxintrq; 619 break; 620#endif 621 default: 622 m_freem(m); 623 return; 624 } 625 626 IF_HANDOFF(inq, m, NULL); 627} 628 629/* 630 * Register (new) link level address. 631 */ 632void 633arc_storelladdr(ifp, lla) 634 struct ifnet *ifp; 635 u_int8_t lla; 636{
|
629 *IF_LLADDR(ifp) = lla;
| 637 ARC_LLADDR(ifp) = lla;
|
630} 631 632/* 633 * Perform common duties while attaching to interface list 634 */ 635void 636arc_ifattach(ifp, lla) 637 struct ifnet *ifp; 638 u_int8_t lla; 639{ 640 struct ifaddr *ifa; 641 struct sockaddr_dl *sdl; 642 struct arccom *ac; 643 644 if_attach(ifp); 645 ifp->if_type = IFT_ARCNET; 646 ifp->if_addrlen = 1; 647 ifp->if_hdrlen = ARC_HDRLEN; 648 ifp->if_mtu = 1500; 649 ifp->if_resolvemulti = arc_resolvemulti; 650 if (ifp->if_baudrate == 0) 651 ifp->if_baudrate = 2500000; 652#if __FreeBSD_version < 500000 653 ifa = ifnet_addrs[ifp->if_index - 1]; 654#else 655 ifa = ifaddr_byindex(ifp->if_index); 656#endif 657 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __FUNCTION__)); 658 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 659 sdl->sdl_type = IFT_ARCNET; 660 sdl->sdl_alen = ifp->if_addrlen; 661 662 if (ifp->if_flags & IFF_BROADCAST) 663 ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 664 665 ac = (struct arccom *)ifp; 666 ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 667 if (lla == 0) { 668 /* XXX this message isn't entirely clear, to me -- cgd */ 669 log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts. Please change it and ifconfig %s%d down up\n", 670 ifp->if_name, ifp->if_unit, ifp->if_name, ifp->if_unit); 671 } 672 arc_storelladdr(ifp, lla); 673 674 ifp->if_broadcastaddr = &arcbroadcastaddr; 675 676 bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 677} 678 679void 680arc_ifdetach(ifp) 681 struct ifnet *ifp; 682{ 683 bpfdetach(ifp); 684 if_detach(ifp); 685} 686 687int 688arc_ioctl(ifp, command, data) 689 struct ifnet *ifp; 690 int command; 691 caddr_t data; 692{ 693 struct ifaddr *ifa = (struct ifaddr *) data; 694 struct ifreq *ifr = (struct ifreq *) data; 695 int error = 0; 696 697 switch (command) { 698 case SIOCSIFADDR: 699 ifp->if_flags |= IFF_UP; 700 switch (ifa->ifa_addr->sa_family) { 701#ifdef INET 702 case AF_INET: 703 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 704 arp_ifinit(ifp, ifa); 705 break; 706#endif 707#ifdef IPX 708 /* 709 * XXX This code is probably wrong 710 */ 711 case AF_IPX: 712 { 713 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 714 715 if (ipx_nullhost(*ina))
| 638} 639 640/* 641 * Perform common duties while attaching to interface list 642 */ 643void 644arc_ifattach(ifp, lla) 645 struct ifnet *ifp; 646 u_int8_t lla; 647{ 648 struct ifaddr *ifa; 649 struct sockaddr_dl *sdl; 650 struct arccom *ac; 651 652 if_attach(ifp); 653 ifp->if_type = IFT_ARCNET; 654 ifp->if_addrlen = 1; 655 ifp->if_hdrlen = ARC_HDRLEN; 656 ifp->if_mtu = 1500; 657 ifp->if_resolvemulti = arc_resolvemulti; 658 if (ifp->if_baudrate == 0) 659 ifp->if_baudrate = 2500000; 660#if __FreeBSD_version < 500000 661 ifa = ifnet_addrs[ifp->if_index - 1]; 662#else 663 ifa = ifaddr_byindex(ifp->if_index); 664#endif 665 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __FUNCTION__)); 666 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 667 sdl->sdl_type = IFT_ARCNET; 668 sdl->sdl_alen = ifp->if_addrlen; 669 670 if (ifp->if_flags & IFF_BROADCAST) 671 ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 672 673 ac = (struct arccom *)ifp; 674 ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 675 if (lla == 0) { 676 /* XXX this message isn't entirely clear, to me -- cgd */ 677 log(LOG_ERR,"%s%d: link address 0 reserved for broadcasts. Please change it and ifconfig %s%d down up\n", 678 ifp->if_name, ifp->if_unit, ifp->if_name, ifp->if_unit); 679 } 680 arc_storelladdr(ifp, lla); 681 682 ifp->if_broadcastaddr = &arcbroadcastaddr; 683 684 bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 685} 686 687void 688arc_ifdetach(ifp) 689 struct ifnet *ifp; 690{ 691 bpfdetach(ifp); 692 if_detach(ifp); 693} 694 695int 696arc_ioctl(ifp, command, data) 697 struct ifnet *ifp; 698 int command; 699 caddr_t data; 700{ 701 struct ifaddr *ifa = (struct ifaddr *) data; 702 struct ifreq *ifr = (struct ifreq *) data; 703 int error = 0; 704 705 switch (command) { 706 case SIOCSIFADDR: 707 ifp->if_flags |= IFF_UP; 708 switch (ifa->ifa_addr->sa_family) { 709#ifdef INET 710 case AF_INET: 711 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 712 arp_ifinit(ifp, ifa); 713 break; 714#endif 715#ifdef IPX 716 /* 717 * XXX This code is probably wrong 718 */ 719 case AF_IPX: 720 { 721 struct ipx_addr *ina = &(IA_SIPX(ifa)->sipx_addr); 722 723 if (ipx_nullhost(*ina))
|
716 ina->x_host.c_host[5] = *IF_LLADDR(ifp);
| 724 ina->x_host.c_host[5] = ARC_LLADDR(ifp);
|
717 else 718 arc_storelladdr(ifp, ina->x_host.c_host[5]); 719 720 /* 721 * Set new address 722 */ 723 ifp->if_init(ifp->if_softc); 724 break; 725 } 726#endif 727 default: 728 ifp->if_init(ifp->if_softc); 729 break; 730 } 731 break; 732 733 case SIOCGIFADDR: 734 { 735 struct sockaddr *sa; 736 737 sa = (struct sockaddr *) &ifr->ifr_data;
| 725 else 726 arc_storelladdr(ifp, ina->x_host.c_host[5]); 727 728 /* 729 * Set new address 730 */ 731 ifp->if_init(ifp->if_softc); 732 break; 733 } 734#endif 735 default: 736 ifp->if_init(ifp->if_softc); 737 break; 738 } 739 break; 740 741 case SIOCGIFADDR: 742 { 743 struct sockaddr *sa; 744 745 sa = (struct sockaddr *) &ifr->ifr_data;
|
738 bcopy(IF_LLADDR(ifp), 739 (caddr_t) sa->sa_data, ARC_ADDR_LEN);
| 746 *(u_int8_t *)sa->sa_data = ARC_LLADDR(ifp);
|
740 } 741 break; 742 743 case SIOCADDMULTI: 744 case SIOCDELMULTI: 745 if (ifr == NULL) 746 error = EAFNOSUPPORT; 747 else { 748 switch (ifr->ifr_addr.sa_family) { 749 case AF_INET: 750 case AF_INET6: 751 error = 0; 752 break; 753 default: 754 error = EAFNOSUPPORT; 755 break; 756 } 757 } 758 break; 759 760 case SIOCSIFMTU: 761 /* 762 * Set the interface MTU. 763 * mtu can't be larger than ARCMTU for RFC1051 764 * and can't be larger than ARC_PHDS_MTU 765 */ 766 if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 767 ifr->ifr_mtu > ARC_PHDS_MAXMTU) 768 error = EINVAL; 769 else 770 ifp->if_mtu = ifr->ifr_mtu; 771 break; 772 } 773 774 return (error); 775} 776 777/* based on ether_resolvemulti() */ 778int 779arc_resolvemulti(ifp, llsa, sa) 780 struct ifnet *ifp; 781 struct sockaddr **llsa; 782 struct sockaddr *sa; 783{ 784 struct sockaddr_dl *sdl; 785 struct sockaddr_in *sin; 786#ifdef INET6 787 struct sockaddr_in6 *sin6; 788#endif 789 790 switch(sa->sa_family) { 791 case AF_LINK: 792 /* 793 * No mapping needed. Just check that it's a valid MC address. 794 */ 795 sdl = (struct sockaddr_dl *)sa; 796 if (*LLADDR(sdl) != arcbroadcastaddr) 797 return EADDRNOTAVAIL; 798 *llsa = 0; 799 return 0; 800#ifdef INET 801 case AF_INET: 802 sin = (struct sockaddr_in *)sa; 803 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 804 return EADDRNOTAVAIL; 805 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 806 M_ZERO); 807 sdl->sdl_len = sizeof *sdl; 808 sdl->sdl_family = AF_LINK; 809 sdl->sdl_index = ifp->if_index; 810 sdl->sdl_type = IFT_ARCNET; 811 sdl->sdl_alen = ARC_ADDR_LEN; 812 *LLADDR(sdl) = 0; 813 *llsa = (struct sockaddr *)sdl; 814 return 0; 815#endif 816#ifdef INET6 817 case AF_INET6: 818 sin6 = (struct sockaddr_in6 *)sa; 819 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 820 /* 821 * An IP6 address of 0 means listen to all 822 * of the Ethernet multicast address used for IP6. 823 * (This is used for multicast routers.) 824 */ 825 ifp->if_flags |= IFF_ALLMULTI; 826 *llsa = 0; 827 return 0; 828 } 829 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 830 return EADDRNOTAVAIL; 831 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 832 M_ZERO); 833 sdl->sdl_len = sizeof *sdl; 834 sdl->sdl_family = AF_LINK; 835 sdl->sdl_index = ifp->if_index; 836 sdl->sdl_type = IFT_ARCNET; 837 sdl->sdl_alen = ARC_ADDR_LEN; 838 *LLADDR(sdl) = 0; 839 *llsa = (struct sockaddr *)sdl; 840 return 0; 841#endif 842 843 default: 844 /* 845 * Well, the text isn't quite right, but it's the name 846 * that counts... 847 */ 848 return EAFNOSUPPORT; 849 } 850}
| 747 } 748 break; 749 750 case SIOCADDMULTI: 751 case SIOCDELMULTI: 752 if (ifr == NULL) 753 error = EAFNOSUPPORT; 754 else { 755 switch (ifr->ifr_addr.sa_family) { 756 case AF_INET: 757 case AF_INET6: 758 error = 0; 759 break; 760 default: 761 error = EAFNOSUPPORT; 762 break; 763 } 764 } 765 break; 766 767 case SIOCSIFMTU: 768 /* 769 * Set the interface MTU. 770 * mtu can't be larger than ARCMTU for RFC1051 771 * and can't be larger than ARC_PHDS_MTU 772 */ 773 if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 774 ifr->ifr_mtu > ARC_PHDS_MAXMTU) 775 error = EINVAL; 776 else 777 ifp->if_mtu = ifr->ifr_mtu; 778 break; 779 } 780 781 return (error); 782} 783 784/* based on ether_resolvemulti() */ 785int 786arc_resolvemulti(ifp, llsa, sa) 787 struct ifnet *ifp; 788 struct sockaddr **llsa; 789 struct sockaddr *sa; 790{ 791 struct sockaddr_dl *sdl; 792 struct sockaddr_in *sin; 793#ifdef INET6 794 struct sockaddr_in6 *sin6; 795#endif 796 797 switch(sa->sa_family) { 798 case AF_LINK: 799 /* 800 * No mapping needed. Just check that it's a valid MC address. 801 */ 802 sdl = (struct sockaddr_dl *)sa; 803 if (*LLADDR(sdl) != arcbroadcastaddr) 804 return EADDRNOTAVAIL; 805 *llsa = 0; 806 return 0; 807#ifdef INET 808 case AF_INET: 809 sin = (struct sockaddr_in *)sa; 810 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 811 return EADDRNOTAVAIL; 812 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 813 M_ZERO); 814 sdl->sdl_len = sizeof *sdl; 815 sdl->sdl_family = AF_LINK; 816 sdl->sdl_index = ifp->if_index; 817 sdl->sdl_type = IFT_ARCNET; 818 sdl->sdl_alen = ARC_ADDR_LEN; 819 *LLADDR(sdl) = 0; 820 *llsa = (struct sockaddr *)sdl; 821 return 0; 822#endif 823#ifdef INET6 824 case AF_INET6: 825 sin6 = (struct sockaddr_in6 *)sa; 826 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 827 /* 828 * An IP6 address of 0 means listen to all 829 * of the Ethernet multicast address used for IP6. 830 * (This is used for multicast routers.) 831 */ 832 ifp->if_flags |= IFF_ALLMULTI; 833 *llsa = 0; 834 return 0; 835 } 836 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 837 return EADDRNOTAVAIL; 838 MALLOC(sdl, struct sockaddr_dl *, sizeof *sdl, M_IFMADDR, 839 M_ZERO); 840 sdl->sdl_len = sizeof *sdl; 841 sdl->sdl_family = AF_LINK; 842 sdl->sdl_index = ifp->if_index; 843 sdl->sdl_type = IFT_ARCNET; 844 sdl->sdl_alen = ARC_ADDR_LEN; 845 *LLADDR(sdl) = 0; 846 *llsa = (struct sockaddr *)sdl; 847 return 0; 848#endif 849 850 default: 851 /* 852 * Well, the text isn't quite right, but it's the name 853 * that counts... 854 */ 855 return EAFNOSUPPORT; 856 } 857}
|