1/* $NetBSD: ip_gre.c,v 1.21 2002/08/14 00:23:30 itojun Exp $ */
| 1/* $NetBSD: ip_gre.c,v 1.21 2002/08/14 00:23:30 itojun Exp $ */
|
2/* $FreeBSD: head/sys/netinet/ip_gre.c 103026 2002-09-06 17:12:50Z sobomax $ */
| 2/* $FreeBSD: head/sys/netinet/ip_gre.c 103032 2002-09-06 18:16:03Z sobomax $ */
|
3 4/* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Heiko W.Rupp <hwr@pilhuhn.de> 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40/* 41 * deencapsulate tunneled packets and send them on 42 * output half is in net/if_gre.[ch] 43 * This currently handles IPPROTO_GRE, IPPROTO_MOBILE 44 */ 45 46#include <sys/cdefs.h>
| 3 4/* 5 * Copyright (c) 1998 The NetBSD Foundation, Inc. 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to The NetBSD Foundation 9 * by Heiko W.Rupp <hwr@pilhuhn.de> 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the NetBSD 22 * Foundation, Inc. and its contributors. 23 * 4. Neither the name of The NetBSD Foundation nor the names of its 24 * contributors may be used to endorse or promote products derived 25 * from this software without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 28 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 29 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 30 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 31 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 32 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 33 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 34 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 35 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 36 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 37 * POSSIBILITY OF SUCH DAMAGE. 38 */ 39 40/* 41 * deencapsulate tunneled packets and send them on 42 * output half is in net/if_gre.[ch] 43 * This currently handles IPPROTO_GRE, IPPROTO_MOBILE 44 */ 45 46#include <sys/cdefs.h>
|
47__RCSID("@(#) $FreeBSD: head/sys/netinet/ip_gre.c 103026 2002-09-06 17:12:50Z sobomax $");
| 47__RCSID("@(#) $FreeBSD: head/sys/netinet/ip_gre.c 103032 2002-09-06 18:16:03Z sobomax $");
|
48 49#include "opt_inet.h" 50#include "opt_ns.h" 51#include "opt_atalk.h" 52#include "bpf.h" 53 54#include <sys/param.h> 55#include <sys/systm.h> 56#include <sys/mbuf.h> 57#include <sys/socket.h> 58#include <sys/socketvar.h> 59#include <sys/protosw.h> 60#include <sys/errno.h> 61#include <sys/time.h> 62#include <sys/kernel.h> 63#include <sys/syslog.h> 64#include <net/bpf.h> 65#include <net/ethernet.h> 66#include <net/if.h> 67#include <net/netisr.h> 68#include <net/route.h> 69#include <net/raw_cb.h> 70 71#ifdef INET 72#include <netinet/in.h> 73#include <netinet/in_var.h> 74#include <netinet/in_systm.h> 75#include <netinet/ip.h> 76#include <netinet/ip_var.h> 77#include <netinet/ip_gre.h> 78#include <machine/in_cksum.h> 79#else 80#error ip_gre input without IP? 81#endif 82 83#ifdef NS 84#include <netns/ns.h> 85#include <netns/ns_if.h> 86#endif 87 88#ifdef NETATALK 89#include <netatalk/at.h> 90#include <netatalk/at_var.h> 91#include <netatalk/at_extern.h> 92#endif 93 94/* Needs IP headers. */ 95#include <net/if_gre.h> 96 97#include <machine/stdarg.h> 98 99#if 1 100void gre_inet_ntoa(struct in_addr in); /* XXX */ 101#endif 102
| 48 49#include "opt_inet.h" 50#include "opt_ns.h" 51#include "opt_atalk.h" 52#include "bpf.h" 53 54#include <sys/param.h> 55#include <sys/systm.h> 56#include <sys/mbuf.h> 57#include <sys/socket.h> 58#include <sys/socketvar.h> 59#include <sys/protosw.h> 60#include <sys/errno.h> 61#include <sys/time.h> 62#include <sys/kernel.h> 63#include <sys/syslog.h> 64#include <net/bpf.h> 65#include <net/ethernet.h> 66#include <net/if.h> 67#include <net/netisr.h> 68#include <net/route.h> 69#include <net/raw_cb.h> 70 71#ifdef INET 72#include <netinet/in.h> 73#include <netinet/in_var.h> 74#include <netinet/in_systm.h> 75#include <netinet/ip.h> 76#include <netinet/ip_var.h> 77#include <netinet/ip_gre.h> 78#include <machine/in_cksum.h> 79#else 80#error ip_gre input without IP? 81#endif 82 83#ifdef NS 84#include <netns/ns.h> 85#include <netns/ns_if.h> 86#endif 87 88#ifdef NETATALK 89#include <netatalk/at.h> 90#include <netatalk/at_var.h> 91#include <netatalk/at_extern.h> 92#endif 93 94/* Needs IP headers. */ 95#include <net/if_gre.h> 96 97#include <machine/stdarg.h> 98 99#if 1 100void gre_inet_ntoa(struct in_addr in); /* XXX */ 101#endif 102
|
103struct gre_softc *gre_lookup __P((struct mbuf *, u_int8_t));
| 103static struct gre_softc *gre_lookup __P((struct mbuf *, u_int8_t));
|
104
| 104
|
105int gre_input2 __P((struct mbuf *, int, u_char));
| 105static int gre_input2 __P((struct mbuf *, int, u_char));
|
106 107/* 108 * De-encapsulate a packet and feed it back through ip input (this 109 * routine is called whenever IP gets a packet with proto type 110 * IPPROTO_GRE and a local destination address). 111 * This really is simple 112 */ 113void 114#if __STDC__ 115gre_input(struct mbuf *m, ...) 116#else 117gre_input(m, va_alist) 118 struct mbuf *m; 119 va_dcl 120#endif 121{ 122 int off, ret, proto; 123 va_list ap; 124 125 va_start(ap, m); 126 off = va_arg(ap, int); 127 va_end(ap); 128 proto = (mtod(m, struct ip *))->ip_p; 129 130 ret = gre_input2(m, off, proto); 131 /* 132 * ret == 0 : packet not processed, meaning that 133 * no matching tunnel that is up is found. 134 * we inject it to raw ip socket to see if anyone picks it up. 135 */ 136 if (ret == 0) 137 rip_input(m, off); 138} 139 140/* 141 * decapsulate. 142 * Does the real work and is called from gre_input() (above) 143 * returns 0 if packet is not yet processed 144 * and 1 if it needs no further processing 145 * proto is the protocol number of the "calling" foo_input() 146 * routine. 147 */ 148
| 106 107/* 108 * De-encapsulate a packet and feed it back through ip input (this 109 * routine is called whenever IP gets a packet with proto type 110 * IPPROTO_GRE and a local destination address). 111 * This really is simple 112 */ 113void 114#if __STDC__ 115gre_input(struct mbuf *m, ...) 116#else 117gre_input(m, va_alist) 118 struct mbuf *m; 119 va_dcl 120#endif 121{ 122 int off, ret, proto; 123 va_list ap; 124 125 va_start(ap, m); 126 off = va_arg(ap, int); 127 va_end(ap); 128 proto = (mtod(m, struct ip *))->ip_p; 129 130 ret = gre_input2(m, off, proto); 131 /* 132 * ret == 0 : packet not processed, meaning that 133 * no matching tunnel that is up is found. 134 * we inject it to raw ip socket to see if anyone picks it up. 135 */ 136 if (ret == 0) 137 rip_input(m, off); 138} 139 140/* 141 * decapsulate. 142 * Does the real work and is called from gre_input() (above) 143 * returns 0 if packet is not yet processed 144 * and 1 if it needs no further processing 145 * proto is the protocol number of the "calling" foo_input() 146 * routine. 147 */ 148
|
149int
| 149static int
|
150gre_input2(struct mbuf *m ,int hlen, u_char proto) 151{ 152 struct greip *gip = mtod(m, struct greip *); 153 int s; 154 struct ifqueue *ifq; 155 struct gre_softc *sc; 156 u_short flags; 157 158 if ((sc = gre_lookup(m, proto)) == NULL) { 159 /* No matching tunnel or tunnel is down. */ 160 return (0); 161 } 162 163 sc->sc_if.if_ipackets++; 164 sc->sc_if.if_ibytes += m->m_pkthdr.len; 165 166 switch (proto) { 167 case IPPROTO_GRE: 168 hlen += sizeof (struct gre_h); 169 170 /* process GRE flags as packet can be of variable len */ 171 flags = ntohs(gip->gi_flags); 172 173 /* Checksum & Offset are present */ 174 if ((flags & GRE_CP) | (flags & GRE_RP)) 175 hlen += 4; 176 /* We don't support routing fields (variable length) */ 177 if (flags & GRE_RP) 178 return(0); 179 if (flags & GRE_KP) 180 hlen += 4; 181 if (flags & GRE_SP) 182 hlen +=4; 183 184 switch (ntohs(gip->gi_ptype)) { /* ethertypes */ 185 case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */ 186 ifq = &ipintrq; /* we are in ip_input */ 187 break; 188 break; 189#ifdef NS 190 case ETHERTYPE_NS: 191 ifq = &nsintrq; 192 schednetisr(NETISR_NS); 193 break; 194#endif 195#ifdef NETATALK 196 case ETHERTYPE_ATALK: 197 ifq = &atintrq1; 198 schednetisr(NETISR_ATALK); 199 break; 200#endif 201 case ETHERTYPE_IPV6: 202 /* FALLTHROUGH */ 203 default: /* others not yet supported */ 204 return(0); 205 } 206 break; 207 default: 208 /* others not yet supported */ 209 return(0); 210 } 211 212 m->m_data += hlen; 213 m->m_len -= hlen; 214 m->m_pkthdr.len -= hlen; 215 216#if NBPF > 0 217 if (sc->sc_if.if_bpf) { 218 struct mbuf m0; 219 u_int32_t af = AF_INET; 220 221 m0.m_next = m; 222 m0.m_len = 4; 223 m0.m_data = (char *)⁡ 224 225 bpf_mtap(&(sc->sc_if), &m0); 226 } 227#endif /*NBPF > 0*/ 228 229 m->m_pkthdr.rcvif = &sc->sc_if; 230 231 s = splnet(); /* possible */ 232 if (_IF_QFULL(ifq)) { 233 _IF_DROP(ifq); 234 m_freem(m); 235 } else { 236 IF_ENQUEUE(ifq,m); 237 } 238 splx(s); 239 240 return(1); /* packet is done, no further processing needed */ 241} 242 243/* 244 * input routine for IPPRPOTO_MOBILE 245 * This is a little bit diffrent from the other modes, as the 246 * encapsulating header was not prepended, but instead inserted 247 * between IP header and payload 248 */ 249 250void 251#if __STDC__ 252gre_mobile_input(struct mbuf *m, ...) 253#else 254gre_mobile_input(m, va_alist) 255 struct mbuf *m; 256 va_dcl 257#endif 258{ 259 struct ip *ip = mtod(m, struct ip *); 260 struct mobip_h *mip = mtod(m, struct mobip_h *); 261 struct ifqueue *ifq; 262 struct gre_softc *sc; 263 int hlen,s; 264 va_list ap; 265 u_char osrc = 0; 266 int msiz; 267 268 va_start(ap,m); 269 hlen = va_arg(ap, int); 270 va_end(ap); 271 272 if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) { 273 /* No matching tunnel or tunnel is down. */ 274 m_freem(m); 275 return; 276 } 277 278 sc->sc_if.if_ipackets++; 279 sc->sc_if.if_ibytes += m->m_pkthdr.len; 280 281 if(ntohs(mip->mh.proto) & MOB_H_SBIT) { 282 osrc = 1; 283 msiz = MOB_H_SIZ_L; 284 mip->mi.ip_src.s_addr = mip->mh.osrc; 285 } else { 286 msiz = MOB_H_SIZ_S; 287 } 288 mip->mi.ip_dst.s_addr = mip->mh.odst; 289 mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); 290 291 if (gre_in_cksum((u_short*)&mip->mh,msiz) != 0) { 292 m_freem(m); 293 return; 294 } 295 296 bcopy((caddr_t)(ip) + (ip->ip_hl << 2) + msiz, (caddr_t)(ip) + 297 (ip->ip_hl << 2), m->m_len - msiz - (ip->ip_hl << 2)); 298 m->m_len -= msiz; 299 m->m_pkthdr.len -= msiz; 300 301 /* 302 * On FreeBSD, rip_input() supplies us with ip->ip_len 303 * already converted into host byteorder and also decreases 304 * it by the lengh of IP header, however, ip_input() expects 305 * that this field is in the original format (network byteorder 306 * and full size of IP packet), so that adjust accordingly. 307 */ 308 ip->ip_len = htons(ip->ip_len + sizeof(struct ip) - msiz); 309 310 ip->ip_sum = 0; 311 ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); 312 313#if NBPF > 0 314 if (sc->sc_if.if_bpf) { 315 struct mbuf m0; 316 u_int af = AF_INET; 317 318 m0.m_next = m; 319 m0.m_len = 4; 320 m0.m_data = (char *)⁡ 321 322 bpf_mtap(&(sc->sc_if), &m0); 323 } 324#endif /*NBPFILTER > 0*/ 325 326 m->m_pkthdr.rcvif = &sc->sc_if; 327 328 ifq = &ipintrq; 329 s = splnet(); /* possible */ 330 if (_IF_QFULL(ifq)) { 331 _IF_DROP(ifq); 332 m_freem(m); 333 } else { 334 IF_ENQUEUE(ifq,m); 335 } 336 splx(s); 337} 338 339/* 340 * Find the gre interface associated with our src/dst/proto set. 341 */
| 150gre_input2(struct mbuf *m ,int hlen, u_char proto) 151{ 152 struct greip *gip = mtod(m, struct greip *); 153 int s; 154 struct ifqueue *ifq; 155 struct gre_softc *sc; 156 u_short flags; 157 158 if ((sc = gre_lookup(m, proto)) == NULL) { 159 /* No matching tunnel or tunnel is down. */ 160 return (0); 161 } 162 163 sc->sc_if.if_ipackets++; 164 sc->sc_if.if_ibytes += m->m_pkthdr.len; 165 166 switch (proto) { 167 case IPPROTO_GRE: 168 hlen += sizeof (struct gre_h); 169 170 /* process GRE flags as packet can be of variable len */ 171 flags = ntohs(gip->gi_flags); 172 173 /* Checksum & Offset are present */ 174 if ((flags & GRE_CP) | (flags & GRE_RP)) 175 hlen += 4; 176 /* We don't support routing fields (variable length) */ 177 if (flags & GRE_RP) 178 return(0); 179 if (flags & GRE_KP) 180 hlen += 4; 181 if (flags & GRE_SP) 182 hlen +=4; 183 184 switch (ntohs(gip->gi_ptype)) { /* ethertypes */ 185 case ETHERTYPE_IP: /* shouldn't need a schednetisr(), as */ 186 ifq = &ipintrq; /* we are in ip_input */ 187 break; 188 break; 189#ifdef NS 190 case ETHERTYPE_NS: 191 ifq = &nsintrq; 192 schednetisr(NETISR_NS); 193 break; 194#endif 195#ifdef NETATALK 196 case ETHERTYPE_ATALK: 197 ifq = &atintrq1; 198 schednetisr(NETISR_ATALK); 199 break; 200#endif 201 case ETHERTYPE_IPV6: 202 /* FALLTHROUGH */ 203 default: /* others not yet supported */ 204 return(0); 205 } 206 break; 207 default: 208 /* others not yet supported */ 209 return(0); 210 } 211 212 m->m_data += hlen; 213 m->m_len -= hlen; 214 m->m_pkthdr.len -= hlen; 215 216#if NBPF > 0 217 if (sc->sc_if.if_bpf) { 218 struct mbuf m0; 219 u_int32_t af = AF_INET; 220 221 m0.m_next = m; 222 m0.m_len = 4; 223 m0.m_data = (char *)⁡ 224 225 bpf_mtap(&(sc->sc_if), &m0); 226 } 227#endif /*NBPF > 0*/ 228 229 m->m_pkthdr.rcvif = &sc->sc_if; 230 231 s = splnet(); /* possible */ 232 if (_IF_QFULL(ifq)) { 233 _IF_DROP(ifq); 234 m_freem(m); 235 } else { 236 IF_ENQUEUE(ifq,m); 237 } 238 splx(s); 239 240 return(1); /* packet is done, no further processing needed */ 241} 242 243/* 244 * input routine for IPPRPOTO_MOBILE 245 * This is a little bit diffrent from the other modes, as the 246 * encapsulating header was not prepended, but instead inserted 247 * between IP header and payload 248 */ 249 250void 251#if __STDC__ 252gre_mobile_input(struct mbuf *m, ...) 253#else 254gre_mobile_input(m, va_alist) 255 struct mbuf *m; 256 va_dcl 257#endif 258{ 259 struct ip *ip = mtod(m, struct ip *); 260 struct mobip_h *mip = mtod(m, struct mobip_h *); 261 struct ifqueue *ifq; 262 struct gre_softc *sc; 263 int hlen,s; 264 va_list ap; 265 u_char osrc = 0; 266 int msiz; 267 268 va_start(ap,m); 269 hlen = va_arg(ap, int); 270 va_end(ap); 271 272 if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) { 273 /* No matching tunnel or tunnel is down. */ 274 m_freem(m); 275 return; 276 } 277 278 sc->sc_if.if_ipackets++; 279 sc->sc_if.if_ibytes += m->m_pkthdr.len; 280 281 if(ntohs(mip->mh.proto) & MOB_H_SBIT) { 282 osrc = 1; 283 msiz = MOB_H_SIZ_L; 284 mip->mi.ip_src.s_addr = mip->mh.osrc; 285 } else { 286 msiz = MOB_H_SIZ_S; 287 } 288 mip->mi.ip_dst.s_addr = mip->mh.odst; 289 mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); 290 291 if (gre_in_cksum((u_short*)&mip->mh,msiz) != 0) { 292 m_freem(m); 293 return; 294 } 295 296 bcopy((caddr_t)(ip) + (ip->ip_hl << 2) + msiz, (caddr_t)(ip) + 297 (ip->ip_hl << 2), m->m_len - msiz - (ip->ip_hl << 2)); 298 m->m_len -= msiz; 299 m->m_pkthdr.len -= msiz; 300 301 /* 302 * On FreeBSD, rip_input() supplies us with ip->ip_len 303 * already converted into host byteorder and also decreases 304 * it by the lengh of IP header, however, ip_input() expects 305 * that this field is in the original format (network byteorder 306 * and full size of IP packet), so that adjust accordingly. 307 */ 308 ip->ip_len = htons(ip->ip_len + sizeof(struct ip) - msiz); 309 310 ip->ip_sum = 0; 311 ip->ip_sum = in_cksum(m, (ip->ip_hl << 2)); 312 313#if NBPF > 0 314 if (sc->sc_if.if_bpf) { 315 struct mbuf m0; 316 u_int af = AF_INET; 317 318 m0.m_next = m; 319 m0.m_len = 4; 320 m0.m_data = (char *)⁡ 321 322 bpf_mtap(&(sc->sc_if), &m0); 323 } 324#endif /*NBPFILTER > 0*/ 325 326 m->m_pkthdr.rcvif = &sc->sc_if; 327 328 ifq = &ipintrq; 329 s = splnet(); /* possible */ 330 if (_IF_QFULL(ifq)) { 331 _IF_DROP(ifq); 332 m_freem(m); 333 } else { 334 IF_ENQUEUE(ifq,m); 335 } 336 splx(s); 337} 338 339/* 340 * Find the gre interface associated with our src/dst/proto set. 341 */
|
342struct gre_softc *
| 342static struct gre_softc *
|
343gre_lookup(m, proto) 344 struct mbuf *m; 345 u_int8_t proto; 346{ 347 struct ip *ip = mtod(m, struct ip *); 348 struct gre_softc *sc; 349 350 for (sc = LIST_FIRST(&gre_softc_list); sc != NULL; 351 sc = LIST_NEXT(sc, sc_list)) { 352 if ((sc->g_dst.s_addr == ip->ip_src.s_addr) && 353 (sc->g_src.s_addr == ip->ip_dst.s_addr) && 354 (sc->g_proto == proto) && 355 ((sc->sc_if.if_flags & IFF_UP) != 0)) 356 return (sc); 357 } 358 359 return (NULL); 360}
| 343gre_lookup(m, proto) 344 struct mbuf *m; 345 u_int8_t proto; 346{ 347 struct ip *ip = mtod(m, struct ip *); 348 struct gre_softc *sc; 349 350 for (sc = LIST_FIRST(&gre_softc_list); sc != NULL; 351 sc = LIST_NEXT(sc, sc_list)) { 352 if ((sc->g_dst.s_addr == ip->ip_src.s_addr) && 353 (sc->g_src.s_addr == ip->ip_dst.s_addr) && 354 (sc->g_proto == proto) && 355 ((sc->sc_if.if_flags & IFF_UP) != 0)) 356 return (sc); 357 } 358 359 return (NULL); 360}
|