if_ethersubr.c (5c9ef378541ddaf6c7606a454ba992c610c09dd0) | if_ethersubr.c (833e8dc5ab711a9485790d950801e32798d55558) |
---|---|
1/*- 2 * Copyright (c) 1982, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 64 unchanged lines hidden (view full) --- 73#include <netinet/if_ether.h> 74#include <netinet/in_rss.h> 75#include <netinet/ip_carp.h> 76#include <netinet/ip_var.h> 77#endif 78#ifdef INET6 79#include <netinet6/nd6.h> 80#endif | 1/*- 2 * Copyright (c) 1982, 1989, 1993 3 * The Regents of the University of California. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright --- 64 unchanged lines hidden (view full) --- 73#include <netinet/if_ether.h> 74#include <netinet/in_rss.h> 75#include <netinet/ip_carp.h> 76#include <netinet/ip_var.h> 77#endif 78#ifdef INET6 79#include <netinet6/nd6.h> 80#endif |
81#include <net/rt_nhops.h> | |
82 83int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m); 84int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp, 85 const struct sockaddr *dst, short *tp, int *hlen); 86 87#include <security/mac/mac_framework.h> 88 89#ifdef CTASSERT --- 25 unchanged lines hidden (view full) --- 115 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 116 117static int ether_resolvemulti(struct ifnet *, struct sockaddr **, 118 struct sockaddr *); 119#ifdef VIMAGE 120static void ether_reassign(struct ifnet *, struct vnet *, char *); 121#endif 122 | 81 82int (*ef_inputp)(struct ifnet*, struct ether_header *eh, struct mbuf *m); 83int (*ef_outputp)(struct ifnet *ifp, struct mbuf **mp, 84 const struct sockaddr *dst, short *tp, int *hlen); 85 86#include <security/mac/mac_framework.h> 87 88#ifdef CTASSERT --- 25 unchanged lines hidden (view full) --- 114 { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 115 116static int ether_resolvemulti(struct ifnet *, struct sockaddr **, 117 struct sockaddr *); 118#ifdef VIMAGE 119static void ether_reassign(struct ifnet *, struct vnet *, char *); 120#endif 121 |
123int ether_output_full(struct ifnet *ifp, struct mbuf *m, 124 const struct sockaddr *dst, struct route *ro); 125int ether_output2(struct ifnet *ifp, struct mbuf *m, struct nhop_prepend *nh, 126 int af); 127 128static int loopback_frame(struct ifnet *ifp, struct mbuf *m, int family, 129 int hlen); 130 131/* XXX: should be in an arp support file, not here */ 132static MALLOC_DEFINE(M_ARPCOM, "arpcom", "802.* interface internals"); 133 | |
134#define ETHER_IS_BROADCAST(addr) \ 135 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0) 136 137#define senderr(e) do { error = (e); goto bad;} while (0) 138 139static void 140update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst) 141{ --- 5 unchanged lines hidden (view full) --- 147 csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR); 148 if (src->m_pkthdr.csum_flags & CSUM_SCTP) 149 csum_flags |= CSUM_SCTP_VALID; 150 dst->m_pkthdr.csum_flags |= csum_flags; 151 if (csum_flags & CSUM_DATA_VALID) 152 dst->m_pkthdr.csum_data = 0xffff; 153} 154 | 122#define ETHER_IS_BROADCAST(addr) \ 123 (bcmp(etherbroadcastaddr, (addr), ETHER_ADDR_LEN) == 0) 124 125#define senderr(e) do { error = (e); goto bad;} while (0) 126 127static void 128update_mbuf_csumflags(struct mbuf *src, struct mbuf *dst) 129{ --- 5 unchanged lines hidden (view full) --- 135 csum_flags |= (CSUM_DATA_VALID|CSUM_PSEUDO_HDR); 136 if (src->m_pkthdr.csum_flags & CSUM_SCTP) 137 csum_flags |= CSUM_SCTP_VALID; 138 dst->m_pkthdr.csum_flags |= csum_flags; 139 if (csum_flags & CSUM_DATA_VALID) 140 dst->m_pkthdr.csum_data = 0xffff; 141} 142 |
155int 156ether_output(struct ifnet *ifp, struct mbuf *m, 157 const struct sockaddr *dst, struct route *ro) 158{ 159 if (ro != NULL && (ro->ro_flags & RT_NHOP)) 160 return (ether_output2(ifp, m, (struct nhop_prepend *)ro->ro_lle, 161 (ro->ro_flags >> 8) & 0xFF)); 162 163 return (ether_output_full(ifp, m, dst, ro)); 164} 165 | |
166/* 167 * Ethernet output routine. 168 * Encapsulate a packet of type family for the local net. 169 * Use trailer local net encapsulation if enough data in first 170 * packet leaves a multiple of 512 bytes of data in remainder. 171 */ 172int | 143/* 144 * Ethernet output routine. 145 * Encapsulate a packet of type family for the local net. 146 * Use trailer local net encapsulation if enough data in first 147 * packet leaves a multiple of 512 bytes of data in remainder. 148 */ 149int |
173ether_output_full(struct ifnet *ifp, struct mbuf *m, | 150ether_output(struct ifnet *ifp, struct mbuf *m, |
174 const struct sockaddr *dst, struct route *ro) 175{ 176 short type; 177 int error = 0, hdrcmplt = 0; 178 u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN]; 179 struct llentry *lle = NULL; 180 struct rtentry *rt0 = NULL; 181 struct ether_header *eh; --- 120 unchanged lines hidden (view full) --- 302 * XXX To make a simplex device behave exactly like a duplex 303 * device, we should copy in the case of sending to our own 304 * ethernet address (thus letting the original actually appear 305 * on the wire). However, we don't do that here for security 306 * reasons and compatibility with the original behavior. 307 */ 308 if ((ifp->if_flags & IFF_SIMPLEX) && loop_copy && 309 ((t = pf_find_mtag(m)) == NULL || !t->routed)) { | 151 const struct sockaddr *dst, struct route *ro) 152{ 153 short type; 154 int error = 0, hdrcmplt = 0; 155 u_char esrc[ETHER_ADDR_LEN], edst[ETHER_ADDR_LEN]; 156 struct llentry *lle = NULL; 157 struct rtentry *rt0 = NULL; 158 struct ether_header *eh; --- 120 unchanged lines hidden (view full) --- 279 * XXX To make a simplex device behave exactly like a duplex 280 * device, we should copy in the case of sending to our own 281 * ethernet address (thus letting the original actually appear 282 * on the wire). However, we don't do that here for security 283 * reasons and compatibility with the original behavior. 284 */ 285 if ((ifp->if_flags & IFF_SIMPLEX) && loop_copy && 286 ((t = pf_find_mtag(m)) == NULL || !t->routed)) { |
310 if ((m->m_flags & M_BCAST) || (bcmp(eh->ether_dhost, 311 eh->ether_shost, ETHER_ADDR_LEN) == 0)) { 312 /* Either broadcast or to-us L2 header */ 313 if (loopback_frame(ifp, m, dst->sa_family, hlen) == 1) 314 return (0); | 287 if (m->m_flags & M_BCAST) { 288 struct mbuf *n; 289 290 /* 291 * Because if_simloop() modifies the packet, we need a 292 * writable copy through m_dup() instead of a readonly 293 * one as m_copy[m] would give us. The alternative would 294 * be to modify if_simloop() to handle the readonly mbuf, 295 * but performancewise it is mostly equivalent (trading 296 * extra data copying vs. extra locking). 297 * 298 * XXX This is a local workaround. A number of less 299 * often used kernel parts suffer from the same bug. 300 * See PR kern/105943 for a proposed general solution. 301 */ 302 if ((n = m_dup(m, M_NOWAIT)) != NULL) { 303 update_mbuf_csumflags(m, n); 304 (void)if_simloop(ifp, n, dst->sa_family, hlen); 305 } else 306 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 307 } else if (bcmp(eh->ether_dhost, eh->ether_shost, 308 ETHER_ADDR_LEN) == 0) { 309 update_mbuf_csumflags(m, m); 310 (void) if_simloop(ifp, m, dst->sa_family, hlen); 311 return (0); /* XXX */ |
315 } 316 } 317 318 /* 319 * Bridges require special output handling. 320 */ 321 if (ifp->if_bridge) { 322 BRIDGE_OUTPUT(ifp, m, error); 323 return (error); 324 } 325 326#if defined(INET) || defined(INET6) 327 if (ifp->if_carp && 328 (error = (*carp_output_p)(ifp, m, dst))) 329 goto bad; 330#endif 331 332 /* Handle ng_ether(4) processing, if any */ | 312 } 313 } 314 315 /* 316 * Bridges require special output handling. 317 */ 318 if (ifp->if_bridge) { 319 BRIDGE_OUTPUT(ifp, m, error); 320 return (error); 321 } 322 323#if defined(INET) || defined(INET6) 324 if (ifp->if_carp && 325 (error = (*carp_output_p)(ifp, m, dst))) 326 goto bad; 327#endif 328 329 /* Handle ng_ether(4) processing, if any */ |
333 if (IFP2AC(ifp)->ac_netgraph != NULL) { | 330 if (ifp->if_l2com != NULL) { |
334 KASSERT(ng_ether_output_p != NULL, 335 ("ng_ether_output_p is NULL")); 336 if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) { 337bad: if (m != NULL) 338 m_freem(m); 339 return (error); 340 } 341 if (m == NULL) 342 return (0); 343 } 344 345 /* Continue with link-layer output */ 346 return ether_output_frame(ifp, m); 347} 348 349/* | 331 KASSERT(ng_ether_output_p != NULL, 332 ("ng_ether_output_p is NULL")); 333 if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) { 334bad: if (m != NULL) 335 m_freem(m); 336 return (error); 337 } 338 if (m == NULL) 339 return (0); 340 } 341 342 /* Continue with link-layer output */ 343 return ether_output_frame(ifp, m); 344} 345 346/* |
350 * We assume this function to be called for 351 * ip[6]_output(), with already pre-compiled L2 header. 352 * 353 * Function assumes all loopback routing is already done on L3, 354 * so the only reason to push packet (copy) to host is M_BCAST flag. 355 */ 356int 357ether_output2(struct ifnet *ifp, struct mbuf *m, struct nhop_prepend *nh,int af) 358{ 359 int error; 360 361#ifdef MAC 362 error = mac_ifnet_check_transmit(ifp, m); 363 if (error) 364 senderr(error); 365#endif 366 367 M_PROFILE(m); 368 if (ifp->if_flags & IFF_MONITOR) 369 senderr(ENETDOWN); 370 if (!((ifp->if_flags & IFF_UP) && 371 (ifp->if_drv_flags & IFF_DRV_RUNNING))) 372 senderr(ENETDOWN); 373 374 if ((ifp->if_flags & IFF_SIMPLEX) && (m->m_flags & M_BCAST)) { 375 /* We have to copy frame to-us */ 376 if (loopback_frame(NH_LIFP(nh), m, af, nh->nh_count) != 0) 377 return (0); 378 } 379 380 /* 381 * Bridges require special output handling. 382 */ 383 if (ifp->if_bridge) { 384 BRIDGE_OUTPUT(ifp, m, error); 385 return (error); 386 } 387 388#if defined(INET) || defined(INET6) 389 if (ifp->if_carp) { 390 struct sockaddr_in dst; 391 memset(&dst, 0, sizeof(dst)); 392 //dst.sin_addr = 393 error = (*carp_output_p)(ifp, m, 394 (const struct sockaddr *)&dst); 395 if (error != 0) 396 goto bad; 397 } 398#endif 399 400 /* Handle ng_ether(4) processing, if any */ 401 if (IFP2AC(ifp)->ac_netgraph != NULL) { 402 KASSERT(ng_ether_output_p != NULL, 403 ("ng_ether_output_p is NULL")); 404 if ((error = (*ng_ether_output_p)(ifp, &m)) != 0) { 405bad: if (m != NULL) 406 m_freem(m); 407 return (error); 408 } 409 if (m == NULL) 410 return (0); 411 } 412 413 /* Continue with link-layer output */ 414 return (ether_output_frame(ifp, m)); 415} 416 417static int 418loopback_frame(struct ifnet *ifp, struct mbuf *m, int family, int hlen) 419{ 420 struct ether_header *eh; 421 422 if (m->m_flags & M_BCAST) { 423 struct mbuf *n; 424 425 /* 426 * Because if_simloop() modifies the packet, we need a 427 * writable copy through m_dup() instead of a readonly 428 * one as m_copy[m] would give us. The alternative would 429 * be to modify if_simloop() to handle the readonly mbuf, 430 * but performancewise it is mostly equivalent (trading 431 * extra data copying vs. extra locking). 432 * 433 * XXX This is a local workaround. A number of less 434 * often used kernel parts suffer from the same bug. 435 * See PR kern/105943 for a proposed general solution. 436 */ 437 if ((n = m_dup(m, M_NOWAIT)) != NULL) { 438 update_mbuf_csumflags(m, n); 439 if_simloop(ifp, n, family, hlen); 440 } else 441 if_inc_counter(ifp, IFCOUNTER_IQDROPS, 1); 442 } else { 443 eh = mtod(m, struct ether_header *); 444 if (bcmp(eh->ether_dhost, eh->ether_shost, 445 ETHER_ADDR_LEN) == 0) { 446 update_mbuf_csumflags(m, m); 447 if_simloop(ifp, m, family, hlen); 448 return (1); 449 } 450 } 451 452 return (0); 453} 454 455/* | |
456 * Ethernet link layer output routine to send a raw frame to the device. 457 * 458 * This assumes that the 14 byte Ethernet header is present and contiguous 459 * in the first mbuf (if BRIDGE'ing). 460 */ 461int 462ether_output_frame(struct ifnet *ifp, struct mbuf *m) 463{ --- 158 unchanged lines hidden (view full) --- 622 ETHER_HDR_LEN - ETHER_TYPE_LEN); 623 m_adj(m, ETHER_VLAN_ENCAP_LEN); 624 eh = mtod(m, struct ether_header *); 625 } 626 627 M_SETFIB(m, ifp->if_fib); 628 629 /* Allow ng_ether(4) to claim this frame. */ | 347 * Ethernet link layer output routine to send a raw frame to the device. 348 * 349 * This assumes that the 14 byte Ethernet header is present and contiguous 350 * in the first mbuf (if BRIDGE'ing). 351 */ 352int 353ether_output_frame(struct ifnet *ifp, struct mbuf *m) 354{ --- 158 unchanged lines hidden (view full) --- 513 ETHER_HDR_LEN - ETHER_TYPE_LEN); 514 m_adj(m, ETHER_VLAN_ENCAP_LEN); 515 eh = mtod(m, struct ether_header *); 516 } 517 518 M_SETFIB(m, ifp->if_fib); 519 520 /* Allow ng_ether(4) to claim this frame. */ |
630 if (IFP2AC(ifp)->ac_netgraph != NULL) { | 521 if (ifp->if_l2com != NULL) { |
631 KASSERT(ng_ether_input_p != NULL, 632 ("%s: ng_ether_input_p is NULL", __func__)); 633 m->m_flags &= ~M_PROMISC; 634 (*ng_ether_input_p)(ifp, &m); 635 if (m == NULL) { 636 CURVNET_RESTORE(); 637 return; 638 } --- 242 unchanged lines hidden (view full) --- 881 return; 882 883discard: 884 /* 885 * Packet is to be discarded. If netgraph is present, 886 * hand the packet to it for last chance processing; 887 * otherwise dispose of it. 888 */ | 522 KASSERT(ng_ether_input_p != NULL, 523 ("%s: ng_ether_input_p is NULL", __func__)); 524 m->m_flags &= ~M_PROMISC; 525 (*ng_ether_input_p)(ifp, &m); 526 if (m == NULL) { 527 CURVNET_RESTORE(); 528 return; 529 } --- 242 unchanged lines hidden (view full) --- 772 return; 773 774discard: 775 /* 776 * Packet is to be discarded. If netgraph is present, 777 * hand the packet to it for last chance processing; 778 * otherwise dispose of it. 779 */ |
889 if (IFP2AC(ifp)->ac_netgraph != NULL) { | 780 if (ifp->if_l2com != NULL) { |
890 KASSERT(ng_ether_input_orphan_p != NULL, 891 ("ng_ether_input_orphan_p is NULL")); 892 /* 893 * Put back the ethernet header so netgraph has a 894 * consistent view of inbound packets. 895 */ 896 M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT); 897 (*ng_ether_input_orphan_p)(ifp, m); --- 69 unchanged lines hidden (view full) --- 967void 968ether_ifdetach(struct ifnet *ifp) 969{ 970 struct sockaddr_dl *sdl; 971 972 sdl = (struct sockaddr_dl *)(ifp->if_addr->ifa_addr); 973 uuid_ether_del(LLADDR(sdl)); 974 | 781 KASSERT(ng_ether_input_orphan_p != NULL, 782 ("ng_ether_input_orphan_p is NULL")); 783 /* 784 * Put back the ethernet header so netgraph has a 785 * consistent view of inbound packets. 786 */ 787 M_PREPEND(m, ETHER_HDR_LEN, M_NOWAIT); 788 (*ng_ether_input_orphan_p)(ifp, m); --- 69 unchanged lines hidden (view full) --- 858void 859ether_ifdetach(struct ifnet *ifp) 860{ 861 struct sockaddr_dl *sdl; 862 863 sdl = (struct sockaddr_dl *)(ifp->if_addr->ifa_addr); 864 uuid_ether_del(LLADDR(sdl)); 865 |
975 if (IFP2AC(ifp)->ac_netgraph != NULL) { | 866 if (ifp->if_l2com != NULL) { |
976 KASSERT(ng_ether_detach_p != NULL, 977 ("ng_ether_detach_p is NULL")); 978 (*ng_ether_detach_p)(ifp); 979 } 980 981 bpfdetach(ifp); 982 if_detach(ifp); 983} 984 985#ifdef VIMAGE 986void 987ether_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused) 988{ 989 | 867 KASSERT(ng_ether_detach_p != NULL, 868 ("ng_ether_detach_p is NULL")); 869 (*ng_ether_detach_p)(ifp); 870 } 871 872 bpfdetach(ifp); 873 if_detach(ifp); 874} 875 876#ifdef VIMAGE 877void 878ether_reassign(struct ifnet *ifp, struct vnet *new_vnet, char *unused __unused) 879{ 880 |
990 if (IFP2AC(ifp)->ac_netgraph != NULL) { | 881 if (ifp->if_l2com != NULL) { |
991 KASSERT(ng_ether_detach_p != NULL, 992 ("ng_ether_detach_p is NULL")); 993 (*ng_ether_detach_p)(ifp); 994 } 995 996 if (ng_ether_attach_p != NULL) { 997 CURVNET_SET_QUIET(new_vnet); 998 (*ng_ether_attach_p)(ifp); --- 194 unchanged lines hidden (view full) --- 1193 /* 1194 * Well, the text isn't quite right, but it's the name 1195 * that counts... 1196 */ 1197 return EAFNOSUPPORT; 1198 } 1199} 1200 | 882 KASSERT(ng_ether_detach_p != NULL, 883 ("ng_ether_detach_p is NULL")); 884 (*ng_ether_detach_p)(ifp); 885 } 886 887 if (ng_ether_attach_p != NULL) { 888 CURVNET_SET_QUIET(new_vnet); 889 (*ng_ether_attach_p)(ifp); --- 194 unchanged lines hidden (view full) --- 1084 /* 1085 * Well, the text isn't quite right, but it's the name 1086 * that counts... 1087 */ 1088 return EAFNOSUPPORT; 1089 } 1090} 1091 |
1201static void* 1202ether_alloc(u_char type, struct ifnet *ifp) 1203{ 1204 struct arpcom *ac; 1205 1206 ac = malloc(sizeof(struct arpcom), M_ARPCOM, M_WAITOK | M_ZERO); 1207 ac->ac_ifp = ifp; 1208 1209 return (ac); 1210} 1211 1212static void 1213ether_free(void *com, u_char type) 1214{ 1215 1216 free(com, M_ARPCOM); 1217} 1218 1219static int 1220ether_modevent(module_t mod, int type, void *data) 1221{ 1222 1223 switch (type) { 1224 case MOD_LOAD: 1225 if_register_com_alloc(IFT_ETHER, ether_alloc, ether_free); 1226 break; 1227 case MOD_UNLOAD: 1228 if_deregister_com_alloc(IFT_ETHER); 1229 break; 1230 default: 1231 return EOPNOTSUPP; 1232 } 1233 1234 return (0); 1235} 1236 | |
1237static moduledata_t ether_mod = { | 1092static moduledata_t ether_mod = { |
1238 "ether", 1239 ether_modevent, 1240 0 | 1093 .name = "ether", |
1241}; 1242 1243void 1244ether_vlan_mtap(struct bpf_if *bp, struct mbuf *m, void *data, u_int dlen) 1245{ 1246 struct ether_vlan_header vlan; 1247 struct mbuf mv, mb; 1248 --- 64 unchanged lines hidden --- | 1094}; 1095 1096void 1097ether_vlan_mtap(struct bpf_if *bp, struct mbuf *m, void *data, u_int dlen) 1098{ 1099 struct ether_vlan_header vlan; 1100 struct mbuf mv, mb; 1101 --- 64 unchanged lines hidden --- |