1/* $NetBSD: ip_gre.c,v 1.29 2003/09/05 23:02:43 itojun Exp $ */ 2 3/*- 4 * Copyright (c) 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Heiko W.Rupp <hwr@pilhuhn.de> --- 24 unchanged lines hidden (view full) --- 33 34/* 35 * deencapsulate tunneled packets and send them on 36 * output half is in net/if_gre.[ch] 37 * This currently handles IPPROTO_GRE, IPPROTO_MOBILE 38 */ 39 40#include <sys/cdefs.h> |
41__FBSDID("$FreeBSD: head/sys/netinet/ip_gre.c 269699 2014-08-08 01:57:15Z kevlo $"); |
42 43#include "opt_inet.h" 44#include "opt_inet6.h" 45 46#include <sys/param.h> 47#include <sys/systm.h> 48#include <sys/mbuf.h> 49#include <sys/socket.h> --- 37 unchanged lines hidden (view full) --- 87static struct mbuf *gre_input2(struct mbuf *, int, u_char); 88 89/* 90 * De-encapsulate a packet and feed it back through ip input (this 91 * routine is called whenever IP gets a packet with proto type 92 * IPPROTO_GRE and a local destination address). 93 * This really is simple 94 */ |
95int 96gre_input(struct mbuf **mp, int *offp, int proto) |
97{ |
98 struct mbuf *m; 99 int off; |
100 |
101 m = *mp; 102 off = *offp; 103 *mp = NULL; |
104 105 m = gre_input2(m, off, proto); 106 107 /* 108 * If no matching tunnel that is up is found. We inject 109 * the mbuf to raw ip socket to see if anyone picks it up. 110 */ |
111 if (m != NULL) { 112 *mp = m; 113 rip_input(mp, offp, proto); 114 } 115 return (IPPROTO_DONE); |
116} 117 118/* 119 * Decapsulate. Does the real work and is called from gre_input() 120 * (above). Returns an mbuf back if packet is not yet processed, 121 * and NULL if it needs no further processing. proto is the protocol 122 * number of the "calling" foo_input() routine. 123 */ --- 90 unchanged lines hidden (view full) --- 214 215/* 216 * input routine for IPPRPOTO_MOBILE 217 * This is a little bit diffrent from the other modes, as the 218 * encapsulating header was not prepended, but instead inserted 219 * between IP header and payload 220 */ 221 |
222int 223gre_mobile_input(struct mbuf **mp, int *offp, int proto) |
224{ 225 struct ip *ip; 226 struct mobip_h *mip; |
227 struct mbuf *m; |
228 struct gre_softc *sc; 229 int msiz; 230 |
231 m = *mp; |
232 if ((sc = gre_lookup(m, IPPROTO_MOBILE)) == NULL) { 233 /* No matching tunnel or tunnel is down. */ 234 m_freem(m); |
235 return (IPPROTO_DONE); |
236 } 237 238 if (m->m_len < sizeof(*mip)) { 239 m = m_pullup(m, sizeof(*mip)); 240 if (m == NULL) |
241 return (IPPROTO_DONE); |
242 } 243 ip = mtod(m, struct ip *); 244 mip = mtod(m, struct mobip_h *); 245 246 GRE2IFP(sc)->if_ipackets++; 247 GRE2IFP(sc)->if_ibytes += m->m_pkthdr.len; 248 249 if (ntohs(mip->mh.proto) & MOB_H_SBIT) { 250 msiz = MOB_H_SIZ_L; 251 mip->mi.ip_src.s_addr = mip->mh.osrc; 252 } else 253 msiz = MOB_H_SIZ_S; 254 255 if (m->m_len < (ip->ip_hl << 2) + msiz) { 256 m = m_pullup(m, (ip->ip_hl << 2) + msiz); 257 if (m == NULL) |
258 return (IPPROTO_DONE); |
259 ip = mtod(m, struct ip *); 260 mip = mtod(m, struct mobip_h *); 261 } 262 263 mip->mi.ip_dst.s_addr = mip->mh.odst; 264 mip->mi.ip_p = (ntohs(mip->mh.proto) >> 8); 265 266 if (gre_in_cksum((u_int16_t *)&mip->mh, msiz) != 0) { 267 m_freem(m); |
268 return (IPPROTO_DONE); |
269 } 270 271 bcopy((caddr_t)(ip) + (ip->ip_hl << 2) + msiz, (caddr_t)(ip) + 272 (ip->ip_hl << 2), m->m_len - msiz - (ip->ip_hl << 2)); 273 m->m_len -= msiz; 274 m->m_pkthdr.len -= msiz; 275 276 /* --- 8 unchanged lines hidden (view full) --- 285 286 if (bpf_peers_present(GRE2IFP(sc)->if_bpf)) { 287 u_int32_t af = AF_INET; 288 bpf_mtap2(GRE2IFP(sc)->if_bpf, &af, sizeof(af), m); 289 } 290 291 if ((GRE2IFP(sc)->if_flags & IFF_MONITOR) != 0) { 292 m_freem(m); |
293 return (IPPROTO_DONE); |
294 } 295 296 m->m_pkthdr.rcvif = GRE2IFP(sc); 297 298 netisr_queue(NETISR_IP, m); |
299 return (IPPROTO_DONE); |
300} 301 302/* 303 * Find the gre interface associated with our src/dst/proto set. 304 * 305 * XXXRW: Need some sort of drain/refcount mechanism so that the softc 306 * reference remains valid after it's returned from gre_lookup(). Right 307 * now, I'm thinking it should be reference-counted with a gre_dropref() --- 25 unchanged lines hidden --- |