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 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/module.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/if_var.h> 60#include <net/netisr.h> 61#include <net/route.h> 62#include <net/if_dl.h> 63#include <net/if_types.h> 64#include <net/if_arc.h> 65#include <net/if_arp.h> 66#include <net/bpf.h> 67#include <net/if_llatbl.h> 68 69#if defined(INET) || defined(INET6) 70#include <netinet/in.h> 71#include <netinet/in_var.h> 72#include <netinet/if_ether.h> 73#endif 74 75#ifdef INET6 76#include <netinet6/nd6.h> 77#endif 78 79#define ARCNET_ALLOW_BROKEN_ARP 80 81static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 82static int arc_resolvemulti(struct ifnet *, struct sockaddr **, 83 struct sockaddr *); 84 85u_int8_t arcbroadcastaddr = 0; 86 87#define ARC_LLADDR(ifp) (*(u_int8_t *)IF_LLADDR(ifp)) 88 89#define senderr(e) { error = (e); goto bad;} 90#define SIN(s) ((const struct sockaddr_in *)(s)) 91 92/* 93 * ARCnet output routine. 94 * Encapsulate a packet of type family for the local net. 95 * Assumes that ifp is actually pointer to arccom structure. 96 */ 97int 98arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 99 struct route *ro) 100{ 101 struct arc_header *ah; 102 int error; 103 u_int8_t atype, adst; 104 int loop_copy = 0; 105 int isphds; 106#if defined(INET) || defined(INET6) 107 int is_gw = 0; 108#endif 109 110 if (!((ifp->if_flags & IFF_UP) && 111 (ifp->if_drv_flags & IFF_DRV_RUNNING))) 112 return(ENETDOWN); /* m, m1 aren't initialized yet */ 113 114 error = 0; 115#if defined(INET) || defined(INET6) 116 if (ro != NULL) 117 is_gw = (ro->ro_flags & RT_HAS_GW) != 0; 118#endif 119 120 switch (dst->sa_family) { 121#ifdef INET 122 case AF_INET: 123 124 /* 125 * For now, use the simple IP addr -> ARCnet addr mapping 126 */ 127 if (m->m_flags & (M_BCAST|M_MCAST)) 128 adst = arcbroadcastaddr; /* ARCnet broadcast address */ 129 else if (ifp->if_flags & IFF_NOARP) 130 adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 131 else { 132 error = arpresolve(ifp, is_gw, m, dst, &adst, NULL); 133 if (error) 134 return (error == EWOULDBLOCK ? 0 : error); 135 } 136 137 atype = (ifp->if_flags & IFF_LINK0) ? 138 ARCTYPE_IP_OLD : ARCTYPE_IP; 139 break; 140 case AF_ARP: 141 { 142 struct arphdr *ah; 143 ah = mtod(m, struct arphdr *); 144 ah->ar_hrd = htons(ARPHRD_ARCNET); 145 146 loop_copy = -1; /* if this is for us, don't do it */ 147 148 switch(ntohs(ah->ar_op)) { 149 case ARPOP_REVREQUEST: 150 case ARPOP_REVREPLY: 151 atype = ARCTYPE_REVARP; 152 break; 153 case ARPOP_REQUEST: 154 case ARPOP_REPLY: 155 default: 156 atype = ARCTYPE_ARP; 157 break; 158 } 159 160 if (m->m_flags & M_BCAST) 161 bcopy(ifp->if_broadcastaddr, &adst, ARC_ADDR_LEN); 162 else 163 bcopy(ar_tha(ah), &adst, ARC_ADDR_LEN); 164 165 } 166 break; 167#endif 168#ifdef INET6 169 case AF_INET6: 170 if ((m->m_flags & M_MCAST) != 0) 171 adst = arcbroadcastaddr; /* ARCnet broadcast address */ 172 else { 173 error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL); 174 if (error != 0) 175 return (error == EWOULDBLOCK ? 0 : error); 176 } 177 atype = ARCTYPE_INET6; 178 break; 179#endif 180 case AF_UNSPEC: 181 { 182 const struct arc_header *ah; 183 184 loop_copy = -1; 185 ah = (const 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 211 isphds = arc_isphds(atype); 212 M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_NOWAIT); 213 if (m == NULL) 214 senderr(ENOBUFS); 215 ah = mtod(m, struct arc_header *); 216 ah->arc_type = atype; 217 ah->arc_dhost = adst; 218 ah->arc_shost = ARC_LLADDR(ifp); 219 if (isphds) { 220 ah->arc_flag = 0; 221 ah->arc_seqid = 0; 222 } 223 224 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 225 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 226 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 227 228 (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); 229 } else if (ah->arc_dhost == ah->arc_shost) { 230 (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); 231 return (0); /* XXX */ 232 } 233 } 234 235 BPF_MTAP(ifp, m); 236 237 error = ifp->if_transmit(ifp, m); 238 239 return (error); 240 241bad: 242 if (m) 243 m_freem(m); 244 return (error); 245} 246 247void 248arc_frag_init(struct ifnet *ifp) 249{ 250 struct arccom *ac; 251 252 ac = (struct arccom *)ifp->if_l2com; 253 ac->curr_frag = 0; 254} 255 256struct mbuf * 257arc_frag_next(struct ifnet *ifp) 258{ 259 struct arccom *ac; 260 struct mbuf *m; 261 struct arc_header *ah; 262 263 ac = (struct arccom *)ifp->if_l2com; 264 if ((m = ac->curr_frag) == NULL) { 265 int tfrags; 266 267 /* dequeue new packet */ 268 IF_DEQUEUE(&ifp->if_snd, m); 269 if (m == NULL) 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 */
| 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 44#include <sys/param.h> 45#include <sys/systm.h> 46#include <sys/kernel.h> 47#include <sys/module.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/if_var.h> 60#include <net/netisr.h> 61#include <net/route.h> 62#include <net/if_dl.h> 63#include <net/if_types.h> 64#include <net/if_arc.h> 65#include <net/if_arp.h> 66#include <net/bpf.h> 67#include <net/if_llatbl.h> 68 69#if defined(INET) || defined(INET6) 70#include <netinet/in.h> 71#include <netinet/in_var.h> 72#include <netinet/if_ether.h> 73#endif 74 75#ifdef INET6 76#include <netinet6/nd6.h> 77#endif 78 79#define ARCNET_ALLOW_BROKEN_ARP 80 81static struct mbuf *arc_defrag(struct ifnet *, struct mbuf *); 82static int arc_resolvemulti(struct ifnet *, struct sockaddr **, 83 struct sockaddr *); 84 85u_int8_t arcbroadcastaddr = 0; 86 87#define ARC_LLADDR(ifp) (*(u_int8_t *)IF_LLADDR(ifp)) 88 89#define senderr(e) { error = (e); goto bad;} 90#define SIN(s) ((const struct sockaddr_in *)(s)) 91 92/* 93 * ARCnet output routine. 94 * Encapsulate a packet of type family for the local net. 95 * Assumes that ifp is actually pointer to arccom structure. 96 */ 97int 98arc_output(struct ifnet *ifp, struct mbuf *m, const struct sockaddr *dst, 99 struct route *ro) 100{ 101 struct arc_header *ah; 102 int error; 103 u_int8_t atype, adst; 104 int loop_copy = 0; 105 int isphds; 106#if defined(INET) || defined(INET6) 107 int is_gw = 0; 108#endif 109 110 if (!((ifp->if_flags & IFF_UP) && 111 (ifp->if_drv_flags & IFF_DRV_RUNNING))) 112 return(ENETDOWN); /* m, m1 aren't initialized yet */ 113 114 error = 0; 115#if defined(INET) || defined(INET6) 116 if (ro != NULL) 117 is_gw = (ro->ro_flags & RT_HAS_GW) != 0; 118#endif 119 120 switch (dst->sa_family) { 121#ifdef INET 122 case AF_INET: 123 124 /* 125 * For now, use the simple IP addr -> ARCnet addr mapping 126 */ 127 if (m->m_flags & (M_BCAST|M_MCAST)) 128 adst = arcbroadcastaddr; /* ARCnet broadcast address */ 129 else if (ifp->if_flags & IFF_NOARP) 130 adst = ntohl(SIN(dst)->sin_addr.s_addr) & 0xFF; 131 else { 132 error = arpresolve(ifp, is_gw, m, dst, &adst, NULL); 133 if (error) 134 return (error == EWOULDBLOCK ? 0 : error); 135 } 136 137 atype = (ifp->if_flags & IFF_LINK0) ? 138 ARCTYPE_IP_OLD : ARCTYPE_IP; 139 break; 140 case AF_ARP: 141 { 142 struct arphdr *ah; 143 ah = mtod(m, struct arphdr *); 144 ah->ar_hrd = htons(ARPHRD_ARCNET); 145 146 loop_copy = -1; /* if this is for us, don't do it */ 147 148 switch(ntohs(ah->ar_op)) { 149 case ARPOP_REVREQUEST: 150 case ARPOP_REVREPLY: 151 atype = ARCTYPE_REVARP; 152 break; 153 case ARPOP_REQUEST: 154 case ARPOP_REPLY: 155 default: 156 atype = ARCTYPE_ARP; 157 break; 158 } 159 160 if (m->m_flags & M_BCAST) 161 bcopy(ifp->if_broadcastaddr, &adst, ARC_ADDR_LEN); 162 else 163 bcopy(ar_tha(ah), &adst, ARC_ADDR_LEN); 164 165 } 166 break; 167#endif 168#ifdef INET6 169 case AF_INET6: 170 if ((m->m_flags & M_MCAST) != 0) 171 adst = arcbroadcastaddr; /* ARCnet broadcast address */ 172 else { 173 error = nd6_resolve(ifp, is_gw, m, dst, &adst, NULL); 174 if (error != 0) 175 return (error == EWOULDBLOCK ? 0 : error); 176 } 177 atype = ARCTYPE_INET6; 178 break; 179#endif 180 case AF_UNSPEC: 181 { 182 const struct arc_header *ah; 183 184 loop_copy = -1; 185 ah = (const 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 211 isphds = arc_isphds(atype); 212 M_PREPEND(m, isphds ? ARC_HDRNEWLEN : ARC_HDRLEN, M_NOWAIT); 213 if (m == NULL) 214 senderr(ENOBUFS); 215 ah = mtod(m, struct arc_header *); 216 ah->arc_type = atype; 217 ah->arc_dhost = adst; 218 ah->arc_shost = ARC_LLADDR(ifp); 219 if (isphds) { 220 ah->arc_flag = 0; 221 ah->arc_seqid = 0; 222 } 223 224 if ((ifp->if_flags & IFF_SIMPLEX) && (loop_copy != -1)) { 225 if ((m->m_flags & M_BCAST) || (loop_copy > 0)) { 226 struct mbuf *n = m_copy(m, 0, (int)M_COPYALL); 227 228 (void) if_simloop(ifp, n, dst->sa_family, ARC_HDRLEN); 229 } else if (ah->arc_dhost == ah->arc_shost) { 230 (void) if_simloop(ifp, m, dst->sa_family, ARC_HDRLEN); 231 return (0); /* XXX */ 232 } 233 } 234 235 BPF_MTAP(ifp, m); 236 237 error = ifp->if_transmit(ifp, m); 238 239 return (error); 240 241bad: 242 if (m) 243 m_freem(m); 244 return (error); 245} 246 247void 248arc_frag_init(struct ifnet *ifp) 249{ 250 struct arccom *ac; 251 252 ac = (struct arccom *)ifp->if_l2com; 253 ac->curr_frag = 0; 254} 255 256struct mbuf * 257arc_frag_next(struct ifnet *ifp) 258{ 259 struct arccom *ac; 260 struct mbuf *m; 261 struct arc_header *ah; 262 263 ac = (struct arccom *)ifp->if_l2com; 264 if ((m = ac->curr_frag) == NULL) { 265 int tfrags; 266 267 /* dequeue new packet */ 268 IF_DEQUEUE(&ifp->if_snd, m); 269 if (m == NULL) 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 */
|
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 285 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 == NULL) { 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 == NULL) 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 == NULL) 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(struct ifnet *ifp, struct mbuf *m) 353{ 354 struct arc_header *ah, *ah1; 355 struct arccom *ac; 356 struct ac_frag *af; 357 struct mbuf *m1; 358 char *s; 359 int newflen; 360 u_char src,dst,typ; 361 362 ac = (struct arccom *)ifp->if_l2com; 363 364 if (m->m_len < ARC_HDRNEWLEN) { 365 m = m_pullup(m, ARC_HDRNEWLEN); 366 if (m == NULL) { 367 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 368 return NULL; 369 } 370 } 371 372 ah = mtod(m, struct arc_header *); 373 typ = ah->arc_type; 374 375 if (!arc_isphds(typ)) 376 return m; 377 378 src = ah->arc_shost; 379 dst = ah->arc_dhost; 380 381 if (ah->arc_flag == 0xff) { 382 m_adj(m, 4); 383 384 if (m->m_len < ARC_HDRNEWLEN) { 385 m = m_pullup(m, ARC_HDRNEWLEN); 386 if (m == NULL) { 387 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 388 return NULL; 389 } 390 } 391 392 ah = mtod(m, struct arc_header *); 393 } 394 395 af = &ac->ac_fragtab[src]; 396 m1 = af->af_packet; 397 s = "debug code error"; 398 399 if (ah->arc_flag & 1) { 400 /* 401 * first fragment. We always initialize, which is 402 * about the right thing to do, as we only want to 403 * accept one fragmented packet per src at a time. 404 */ 405 if (m1 != NULL) 406 m_freem(m1); 407 408 af->af_packet = m; 409 m1 = m; 410 af->af_maxflag = ah->arc_flag; 411 af->af_lastseen = 0; 412 af->af_seqid = ah->arc_seqid; 413 414 return NULL; 415 /* notreached */ 416 } else { 417 /* check for unfragmented packet */ 418 if (ah->arc_flag == 0) 419 return m; 420 421 /* do we have a first packet from that src? */ 422 if (m1 == NULL) { 423 s = "no first frag"; 424 goto outofseq; 425 } 426 427 ah1 = mtod(m1, struct arc_header *); 428 429 if (ah->arc_seqid != ah1->arc_seqid) { 430 s = "seqid differs"; 431 goto outofseq; 432 } 433 434 if (typ != ah1->arc_type) { 435 s = "type differs"; 436 goto outofseq; 437 } 438 439 if (dst != ah1->arc_dhost) { 440 s = "dest host differs"; 441 goto outofseq; 442 } 443 444 /* typ, seqid and dst are ok here. */ 445 446 if (ah->arc_flag == af->af_lastseen) { 447 m_freem(m); 448 return NULL; 449 } 450 451 if (ah->arc_flag == af->af_lastseen + 2) { 452 /* ok, this is next fragment */ 453 af->af_lastseen = ah->arc_flag; 454 m_adj(m,ARC_HDRNEWLEN); 455 456 /* 457 * m_cat might free the first mbuf (with pkthdr) 458 * in 2nd chain; therefore: 459 */ 460 461 newflen = m->m_pkthdr.len; 462 463 m_cat(m1,m); 464 465 m1->m_pkthdr.len += newflen; 466 467 /* is it the last one? */ 468 if (af->af_lastseen > af->af_maxflag) { 469 af->af_packet = NULL; 470 return(m1); 471 } else 472 return NULL; 473 } 474 s = "other reason"; 475 /* if all else fails, it is out of sequence, too */ 476 } 477outofseq: 478 if (m1) { 479 m_freem(m1); 480 af->af_packet = NULL; 481 } 482 483 if (m) 484 m_freem(m); 485 486 log(LOG_INFO,"%s: got out of seq. packet: %s\n", 487 ifp->if_xname, s); 488 489 return NULL; 490} 491 492/* 493 * return 1 if Packet Header Definition Standard, else 0. 494 * For now: old IP, old ARP aren't obviously. Lacking correct information, 495 * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 496 * (Apple and Novell corporations were involved, among others, in PHDS work). 497 * Easiest is to assume that everybody else uses that, too. 498 */ 499int 500arc_isphds(u_int8_t type) 501{ 502 return (type != ARCTYPE_IP_OLD && 503 type != ARCTYPE_ARP_OLD && 504 type != ARCTYPE_DIAGNOSE); 505} 506 507/* 508 * Process a received Arcnet packet; 509 * the packet is in the mbuf chain m with 510 * the ARCnet header. 511 */ 512void 513arc_input(struct ifnet *ifp, struct mbuf *m) 514{ 515 struct arc_header *ah; 516 int isr; 517 u_int8_t atype; 518 519 if ((ifp->if_flags & IFF_UP) == 0) { 520 m_freem(m); 521 return; 522 } 523 524 /* possibly defragment: */ 525 m = arc_defrag(ifp, m); 526 if (m == NULL) 527 return; 528 529 BPF_MTAP(ifp, m); 530 531 ah = mtod(m, struct arc_header *); 532 /* does this belong to us? */ 533 if ((ifp->if_flags & IFF_PROMISC) == 0 534 && ah->arc_dhost != arcbroadcastaddr 535 && ah->arc_dhost != ARC_LLADDR(ifp)) { 536 m_freem(m); 537 return; 538 } 539 540 if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); 541 542 if (ah->arc_dhost == arcbroadcastaddr) { 543 m->m_flags |= M_BCAST|M_MCAST; 544 if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); 545 } 546 547 atype = ah->arc_type; 548 switch (atype) { 549#ifdef INET 550 case ARCTYPE_IP: 551 m_adj(m, ARC_HDRNEWLEN); 552 isr = NETISR_IP; 553 break; 554 555 case ARCTYPE_IP_OLD: 556 m_adj(m, ARC_HDRLEN); 557 isr = NETISR_IP; 558 break; 559 560 case ARCTYPE_ARP: 561 if (ifp->if_flags & IFF_NOARP) { 562 /* Discard packet if ARP is disabled on interface */ 563 m_freem(m); 564 return; 565 } 566 m_adj(m, ARC_HDRNEWLEN); 567 isr = NETISR_ARP; 568#ifdef ARCNET_ALLOW_BROKEN_ARP 569 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 570#endif 571 break; 572 573 case ARCTYPE_ARP_OLD: 574 if (ifp->if_flags & IFF_NOARP) { 575 /* Discard packet if ARP is disabled on interface */ 576 m_freem(m); 577 return; 578 } 579 m_adj(m, ARC_HDRLEN); 580 isr = NETISR_ARP; 581#ifdef ARCNET_ALLOW_BROKEN_ARP 582 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 583#endif 584 break; 585#endif 586#ifdef INET6 587 case ARCTYPE_INET6: 588 m_adj(m, ARC_HDRNEWLEN); 589 isr = NETISR_IPV6; 590 break; 591#endif 592 default: 593 m_freem(m); 594 return; 595 } 596 M_SETFIB(m, ifp->if_fib); 597 netisr_dispatch(isr, m); 598} 599 600/* 601 * Register (new) link level address. 602 */ 603void 604arc_storelladdr(struct ifnet *ifp, u_int8_t lla) 605{ 606 ARC_LLADDR(ifp) = lla; 607} 608 609/* 610 * Perform common duties while attaching to interface list 611 */ 612void 613arc_ifattach(struct ifnet *ifp, u_int8_t lla) 614{ 615 struct ifaddr *ifa; 616 struct sockaddr_dl *sdl; 617 struct arccom *ac; 618 619 if_attach(ifp); 620 ifp->if_addrlen = 1; 621 ifp->if_hdrlen = ARC_HDRLEN; 622 ifp->if_mtu = 1500; 623 ifp->if_resolvemulti = arc_resolvemulti; 624 if (ifp->if_baudrate == 0) 625 ifp->if_baudrate = 2500000; 626 ifa = ifp->if_addr; 627 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); 628 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 629 sdl->sdl_type = IFT_ARCNET; 630 sdl->sdl_alen = ifp->if_addrlen; 631 632 if (ifp->if_flags & IFF_BROADCAST) 633 ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 634 635 ac = (struct arccom *)ifp->if_l2com; 636 ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 637 if (lla == 0) { 638 /* XXX this message isn't entirely clear, to me -- cgd */ 639 log(LOG_ERR,"%s: link address 0 reserved for broadcasts. Please change it and ifconfig %s down up\n", 640 ifp->if_xname, ifp->if_xname); 641 } 642 arc_storelladdr(ifp, lla); 643 644 ifp->if_broadcastaddr = &arcbroadcastaddr; 645 646 bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 647} 648 649void 650arc_ifdetach(struct ifnet *ifp) 651{ 652 bpfdetach(ifp); 653 if_detach(ifp); 654} 655 656int 657arc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 658{ 659 struct ifaddr *ifa = (struct ifaddr *) data; 660 struct ifreq *ifr = (struct ifreq *) data; 661 int error = 0; 662 663 switch (command) { 664 case SIOCSIFADDR: 665 ifp->if_flags |= IFF_UP; 666 switch (ifa->ifa_addr->sa_family) { 667#ifdef INET 668 case AF_INET: 669 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 670 arp_ifinit(ifp, ifa); 671 break; 672#endif 673 default: 674 ifp->if_init(ifp->if_softc); 675 break; 676 } 677 break; 678 679 case SIOCGIFADDR: 680 { 681 struct sockaddr *sa; 682 683 sa = (struct sockaddr *) &ifr->ifr_data; 684 *(u_int8_t *)sa->sa_data = ARC_LLADDR(ifp); 685 } 686 break; 687 688 case SIOCADDMULTI: 689 case SIOCDELMULTI: 690 if (ifr == NULL) 691 error = EAFNOSUPPORT; 692 else { 693 switch (ifr->ifr_addr.sa_family) { 694 case AF_INET: 695 case AF_INET6: 696 error = 0; 697 break; 698 default: 699 error = EAFNOSUPPORT; 700 break; 701 } 702 } 703 break; 704 705 case SIOCSIFMTU: 706 /* 707 * Set the interface MTU. 708 * mtu can't be larger than ARCMTU for RFC1051 709 * and can't be larger than ARC_PHDS_MTU 710 */ 711 if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 712 ifr->ifr_mtu > ARC_PHDS_MAXMTU) 713 error = EINVAL; 714 else 715 ifp->if_mtu = ifr->ifr_mtu; 716 break; 717 } 718 719 return (error); 720} 721 722/* based on ether_resolvemulti() */ 723int 724arc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 725 struct sockaddr *sa) 726{ 727 struct sockaddr_dl *sdl; 728#ifdef INET 729 struct sockaddr_in *sin; 730#endif 731#ifdef INET6 732 struct sockaddr_in6 *sin6; 733#endif 734 735 switch(sa->sa_family) { 736 case AF_LINK: 737 /* 738 * No mapping needed. Just check that it's a valid MC address. 739 */ 740 sdl = (struct sockaddr_dl *)sa; 741 if (*LLADDR(sdl) != arcbroadcastaddr) 742 return EADDRNOTAVAIL; 743 *llsa = NULL; 744 return 0; 745#ifdef INET 746 case AF_INET: 747 sin = (struct sockaddr_in *)sa; 748 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 749 return EADDRNOTAVAIL; 750 sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); 751 sdl->sdl_alen = ARC_ADDR_LEN; 752 *LLADDR(sdl) = 0; 753 *llsa = (struct sockaddr *)sdl; 754 return 0; 755#endif 756#ifdef INET6 757 case AF_INET6: 758 sin6 = (struct sockaddr_in6 *)sa; 759 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 760 /* 761 * An IP6 address of 0 means listen to all 762 * of the Ethernet multicast address used for IP6. 763 * (This is used for multicast routers.) 764 */ 765 ifp->if_flags |= IFF_ALLMULTI; 766 *llsa = NULL; 767 return 0; 768 } 769 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 770 return EADDRNOTAVAIL; 771 sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); 772 sdl->sdl_alen = ARC_ADDR_LEN; 773 *LLADDR(sdl) = 0; 774 *llsa = (struct sockaddr *)sdl; 775 return 0; 776#endif 777 778 default: 779 /* 780 * Well, the text isn't quite right, but it's the name 781 * that counts... 782 */ 783 return EAFNOSUPPORT; 784 } 785} 786 787static MALLOC_DEFINE(M_ARCCOM, "arccom", "ARCNET interface internals"); 788 789static void* 790arc_alloc(u_char type, struct ifnet *ifp) 791{ 792 struct arccom *ac; 793 794 ac = malloc(sizeof(struct arccom), M_ARCCOM, M_WAITOK | M_ZERO); 795 ac->ac_ifp = ifp; 796 797 return (ac); 798} 799 800static void 801arc_free(void *com, u_char type) 802{ 803 804 free(com, M_ARCCOM); 805} 806 807static int 808arc_modevent(module_t mod, int type, void *data) 809{ 810 811 switch (type) { 812 case MOD_LOAD: 813 if_register_com_alloc(IFT_ARCNET, arc_alloc, arc_free); 814 break; 815 case MOD_UNLOAD: 816 if_deregister_com_alloc(IFT_ARCNET); 817 break; 818 default: 819 return EOPNOTSUPP; 820 } 821 822 return (0); 823} 824 825static moduledata_t arc_mod = { 826 "arcnet", 827 arc_modevent, 828 0 829}; 830 831DECLARE_MODULE(arcnet, arc_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); 832MODULE_VERSION(arcnet, 1);
| 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 285 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 == NULL) { 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 == NULL) 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 == NULL) 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(struct ifnet *ifp, struct mbuf *m) 353{ 354 struct arc_header *ah, *ah1; 355 struct arccom *ac; 356 struct ac_frag *af; 357 struct mbuf *m1; 358 char *s; 359 int newflen; 360 u_char src,dst,typ; 361 362 ac = (struct arccom *)ifp->if_l2com; 363 364 if (m->m_len < ARC_HDRNEWLEN) { 365 m = m_pullup(m, ARC_HDRNEWLEN); 366 if (m == NULL) { 367 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 368 return NULL; 369 } 370 } 371 372 ah = mtod(m, struct arc_header *); 373 typ = ah->arc_type; 374 375 if (!arc_isphds(typ)) 376 return m; 377 378 src = ah->arc_shost; 379 dst = ah->arc_dhost; 380 381 if (ah->arc_flag == 0xff) { 382 m_adj(m, 4); 383 384 if (m->m_len < ARC_HDRNEWLEN) { 385 m = m_pullup(m, ARC_HDRNEWLEN); 386 if (m == NULL) { 387 if_inc_counter(ifp, IFCOUNTER_IERRORS, 1); 388 return NULL; 389 } 390 } 391 392 ah = mtod(m, struct arc_header *); 393 } 394 395 af = &ac->ac_fragtab[src]; 396 m1 = af->af_packet; 397 s = "debug code error"; 398 399 if (ah->arc_flag & 1) { 400 /* 401 * first fragment. We always initialize, which is 402 * about the right thing to do, as we only want to 403 * accept one fragmented packet per src at a time. 404 */ 405 if (m1 != NULL) 406 m_freem(m1); 407 408 af->af_packet = m; 409 m1 = m; 410 af->af_maxflag = ah->arc_flag; 411 af->af_lastseen = 0; 412 af->af_seqid = ah->arc_seqid; 413 414 return NULL; 415 /* notreached */ 416 } else { 417 /* check for unfragmented packet */ 418 if (ah->arc_flag == 0) 419 return m; 420 421 /* do we have a first packet from that src? */ 422 if (m1 == NULL) { 423 s = "no first frag"; 424 goto outofseq; 425 } 426 427 ah1 = mtod(m1, struct arc_header *); 428 429 if (ah->arc_seqid != ah1->arc_seqid) { 430 s = "seqid differs"; 431 goto outofseq; 432 } 433 434 if (typ != ah1->arc_type) { 435 s = "type differs"; 436 goto outofseq; 437 } 438 439 if (dst != ah1->arc_dhost) { 440 s = "dest host differs"; 441 goto outofseq; 442 } 443 444 /* typ, seqid and dst are ok here. */ 445 446 if (ah->arc_flag == af->af_lastseen) { 447 m_freem(m); 448 return NULL; 449 } 450 451 if (ah->arc_flag == af->af_lastseen + 2) { 452 /* ok, this is next fragment */ 453 af->af_lastseen = ah->arc_flag; 454 m_adj(m,ARC_HDRNEWLEN); 455 456 /* 457 * m_cat might free the first mbuf (with pkthdr) 458 * in 2nd chain; therefore: 459 */ 460 461 newflen = m->m_pkthdr.len; 462 463 m_cat(m1,m); 464 465 m1->m_pkthdr.len += newflen; 466 467 /* is it the last one? */ 468 if (af->af_lastseen > af->af_maxflag) { 469 af->af_packet = NULL; 470 return(m1); 471 } else 472 return NULL; 473 } 474 s = "other reason"; 475 /* if all else fails, it is out of sequence, too */ 476 } 477outofseq: 478 if (m1) { 479 m_freem(m1); 480 af->af_packet = NULL; 481 } 482 483 if (m) 484 m_freem(m); 485 486 log(LOG_INFO,"%s: got out of seq. packet: %s\n", 487 ifp->if_xname, s); 488 489 return NULL; 490} 491 492/* 493 * return 1 if Packet Header Definition Standard, else 0. 494 * For now: old IP, old ARP aren't obviously. Lacking correct information, 495 * we guess that besides new IP and new ARP also IPX and APPLETALK are PHDS. 496 * (Apple and Novell corporations were involved, among others, in PHDS work). 497 * Easiest is to assume that everybody else uses that, too. 498 */ 499int 500arc_isphds(u_int8_t type) 501{ 502 return (type != ARCTYPE_IP_OLD && 503 type != ARCTYPE_ARP_OLD && 504 type != ARCTYPE_DIAGNOSE); 505} 506 507/* 508 * Process a received Arcnet packet; 509 * the packet is in the mbuf chain m with 510 * the ARCnet header. 511 */ 512void 513arc_input(struct ifnet *ifp, struct mbuf *m) 514{ 515 struct arc_header *ah; 516 int isr; 517 u_int8_t atype; 518 519 if ((ifp->if_flags & IFF_UP) == 0) { 520 m_freem(m); 521 return; 522 } 523 524 /* possibly defragment: */ 525 m = arc_defrag(ifp, m); 526 if (m == NULL) 527 return; 528 529 BPF_MTAP(ifp, m); 530 531 ah = mtod(m, struct arc_header *); 532 /* does this belong to us? */ 533 if ((ifp->if_flags & IFF_PROMISC) == 0 534 && ah->arc_dhost != arcbroadcastaddr 535 && ah->arc_dhost != ARC_LLADDR(ifp)) { 536 m_freem(m); 537 return; 538 } 539 540 if_inc_counter(ifp, IFCOUNTER_IBYTES, m->m_pkthdr.len); 541 542 if (ah->arc_dhost == arcbroadcastaddr) { 543 m->m_flags |= M_BCAST|M_MCAST; 544 if_inc_counter(ifp, IFCOUNTER_IMCASTS, 1); 545 } 546 547 atype = ah->arc_type; 548 switch (atype) { 549#ifdef INET 550 case ARCTYPE_IP: 551 m_adj(m, ARC_HDRNEWLEN); 552 isr = NETISR_IP; 553 break; 554 555 case ARCTYPE_IP_OLD: 556 m_adj(m, ARC_HDRLEN); 557 isr = NETISR_IP; 558 break; 559 560 case ARCTYPE_ARP: 561 if (ifp->if_flags & IFF_NOARP) { 562 /* Discard packet if ARP is disabled on interface */ 563 m_freem(m); 564 return; 565 } 566 m_adj(m, ARC_HDRNEWLEN); 567 isr = NETISR_ARP; 568#ifdef ARCNET_ALLOW_BROKEN_ARP 569 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 570#endif 571 break; 572 573 case ARCTYPE_ARP_OLD: 574 if (ifp->if_flags & IFF_NOARP) { 575 /* Discard packet if ARP is disabled on interface */ 576 m_freem(m); 577 return; 578 } 579 m_adj(m, ARC_HDRLEN); 580 isr = NETISR_ARP; 581#ifdef ARCNET_ALLOW_BROKEN_ARP 582 mtod(m, struct arphdr *)->ar_pro = htons(ETHERTYPE_IP); 583#endif 584 break; 585#endif 586#ifdef INET6 587 case ARCTYPE_INET6: 588 m_adj(m, ARC_HDRNEWLEN); 589 isr = NETISR_IPV6; 590 break; 591#endif 592 default: 593 m_freem(m); 594 return; 595 } 596 M_SETFIB(m, ifp->if_fib); 597 netisr_dispatch(isr, m); 598} 599 600/* 601 * Register (new) link level address. 602 */ 603void 604arc_storelladdr(struct ifnet *ifp, u_int8_t lla) 605{ 606 ARC_LLADDR(ifp) = lla; 607} 608 609/* 610 * Perform common duties while attaching to interface list 611 */ 612void 613arc_ifattach(struct ifnet *ifp, u_int8_t lla) 614{ 615 struct ifaddr *ifa; 616 struct sockaddr_dl *sdl; 617 struct arccom *ac; 618 619 if_attach(ifp); 620 ifp->if_addrlen = 1; 621 ifp->if_hdrlen = ARC_HDRLEN; 622 ifp->if_mtu = 1500; 623 ifp->if_resolvemulti = arc_resolvemulti; 624 if (ifp->if_baudrate == 0) 625 ifp->if_baudrate = 2500000; 626 ifa = ifp->if_addr; 627 KASSERT(ifa != NULL, ("%s: no lladdr!\n", __func__)); 628 sdl = (struct sockaddr_dl *)ifa->ifa_addr; 629 sdl->sdl_type = IFT_ARCNET; 630 sdl->sdl_alen = ifp->if_addrlen; 631 632 if (ifp->if_flags & IFF_BROADCAST) 633 ifp->if_flags |= IFF_MULTICAST|IFF_ALLMULTI; 634 635 ac = (struct arccom *)ifp->if_l2com; 636 ac->ac_seqid = (time_second) & 0xFFFF; /* try to make seqid unique */ 637 if (lla == 0) { 638 /* XXX this message isn't entirely clear, to me -- cgd */ 639 log(LOG_ERR,"%s: link address 0 reserved for broadcasts. Please change it and ifconfig %s down up\n", 640 ifp->if_xname, ifp->if_xname); 641 } 642 arc_storelladdr(ifp, lla); 643 644 ifp->if_broadcastaddr = &arcbroadcastaddr; 645 646 bpfattach(ifp, DLT_ARCNET, ARC_HDRLEN); 647} 648 649void 650arc_ifdetach(struct ifnet *ifp) 651{ 652 bpfdetach(ifp); 653 if_detach(ifp); 654} 655 656int 657arc_ioctl(struct ifnet *ifp, u_long command, caddr_t data) 658{ 659 struct ifaddr *ifa = (struct ifaddr *) data; 660 struct ifreq *ifr = (struct ifreq *) data; 661 int error = 0; 662 663 switch (command) { 664 case SIOCSIFADDR: 665 ifp->if_flags |= IFF_UP; 666 switch (ifa->ifa_addr->sa_family) { 667#ifdef INET 668 case AF_INET: 669 ifp->if_init(ifp->if_softc); /* before arpwhohas */ 670 arp_ifinit(ifp, ifa); 671 break; 672#endif 673 default: 674 ifp->if_init(ifp->if_softc); 675 break; 676 } 677 break; 678 679 case SIOCGIFADDR: 680 { 681 struct sockaddr *sa; 682 683 sa = (struct sockaddr *) &ifr->ifr_data; 684 *(u_int8_t *)sa->sa_data = ARC_LLADDR(ifp); 685 } 686 break; 687 688 case SIOCADDMULTI: 689 case SIOCDELMULTI: 690 if (ifr == NULL) 691 error = EAFNOSUPPORT; 692 else { 693 switch (ifr->ifr_addr.sa_family) { 694 case AF_INET: 695 case AF_INET6: 696 error = 0; 697 break; 698 default: 699 error = EAFNOSUPPORT; 700 break; 701 } 702 } 703 break; 704 705 case SIOCSIFMTU: 706 /* 707 * Set the interface MTU. 708 * mtu can't be larger than ARCMTU for RFC1051 709 * and can't be larger than ARC_PHDS_MTU 710 */ 711 if (((ifp->if_flags & IFF_LINK0) && ifr->ifr_mtu > ARCMTU) || 712 ifr->ifr_mtu > ARC_PHDS_MAXMTU) 713 error = EINVAL; 714 else 715 ifp->if_mtu = ifr->ifr_mtu; 716 break; 717 } 718 719 return (error); 720} 721 722/* based on ether_resolvemulti() */ 723int 724arc_resolvemulti(struct ifnet *ifp, struct sockaddr **llsa, 725 struct sockaddr *sa) 726{ 727 struct sockaddr_dl *sdl; 728#ifdef INET 729 struct sockaddr_in *sin; 730#endif 731#ifdef INET6 732 struct sockaddr_in6 *sin6; 733#endif 734 735 switch(sa->sa_family) { 736 case AF_LINK: 737 /* 738 * No mapping needed. Just check that it's a valid MC address. 739 */ 740 sdl = (struct sockaddr_dl *)sa; 741 if (*LLADDR(sdl) != arcbroadcastaddr) 742 return EADDRNOTAVAIL; 743 *llsa = NULL; 744 return 0; 745#ifdef INET 746 case AF_INET: 747 sin = (struct sockaddr_in *)sa; 748 if (!IN_MULTICAST(ntohl(sin->sin_addr.s_addr))) 749 return EADDRNOTAVAIL; 750 sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); 751 sdl->sdl_alen = ARC_ADDR_LEN; 752 *LLADDR(sdl) = 0; 753 *llsa = (struct sockaddr *)sdl; 754 return 0; 755#endif 756#ifdef INET6 757 case AF_INET6: 758 sin6 = (struct sockaddr_in6 *)sa; 759 if (IN6_IS_ADDR_UNSPECIFIED(&sin6->sin6_addr)) { 760 /* 761 * An IP6 address of 0 means listen to all 762 * of the Ethernet multicast address used for IP6. 763 * (This is used for multicast routers.) 764 */ 765 ifp->if_flags |= IFF_ALLMULTI; 766 *llsa = NULL; 767 return 0; 768 } 769 if (!IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr)) 770 return EADDRNOTAVAIL; 771 sdl = link_init_sdl(ifp, *llsa, IFT_ETHER); 772 sdl->sdl_alen = ARC_ADDR_LEN; 773 *LLADDR(sdl) = 0; 774 *llsa = (struct sockaddr *)sdl; 775 return 0; 776#endif 777 778 default: 779 /* 780 * Well, the text isn't quite right, but it's the name 781 * that counts... 782 */ 783 return EAFNOSUPPORT; 784 } 785} 786 787static MALLOC_DEFINE(M_ARCCOM, "arccom", "ARCNET interface internals"); 788 789static void* 790arc_alloc(u_char type, struct ifnet *ifp) 791{ 792 struct arccom *ac; 793 794 ac = malloc(sizeof(struct arccom), M_ARCCOM, M_WAITOK | M_ZERO); 795 ac->ac_ifp = ifp; 796 797 return (ac); 798} 799 800static void 801arc_free(void *com, u_char type) 802{ 803 804 free(com, M_ARCCOM); 805} 806 807static int 808arc_modevent(module_t mod, int type, void *data) 809{ 810 811 switch (type) { 812 case MOD_LOAD: 813 if_register_com_alloc(IFT_ARCNET, arc_alloc, arc_free); 814 break; 815 case MOD_UNLOAD: 816 if_deregister_com_alloc(IFT_ARCNET); 817 break; 818 default: 819 return EOPNOTSUPP; 820 } 821 822 return (0); 823} 824 825static moduledata_t arc_mod = { 826 "arcnet", 827 arc_modevent, 828 0 829}; 830 831DECLARE_MODULE(arcnet, arc_mod, SI_SUB_INIT_IF, SI_ORDER_ANY); 832MODULE_VERSION(arcnet, 1);
|