Deleted Added
sdiff udiff text old ( 55009 ) new ( 62587 )
full compact
1/*
2 * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
3 * 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

--- 11 unchanged lines hidden (view full) ---

20 * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * $FreeBSD: head/sys/netinet6/in6_gif.c 55009 1999-12-22 19:13:38Z shin $
30 */
31
32/*
33 * in6_gif.c
34 */
35
36#include "opt_inet.h"
37
38#include <sys/param.h>
39#include <sys/systm.h>
40#include <sys/socket.h>
41#include <sys/sockio.h>
42#include <sys/mbuf.h>
43#include <sys/errno.h>
44#include <sys/protosw.h>
45
46#include <net/if.h>
47#include <net/route.h>
48
49#include <netinet/in.h>
50#include <netinet/in_systm.h>
51#ifdef INET
52#include <netinet/ip.h>
53#endif
54#include <netinet6/ip6.h>
55#include <netinet6/ip6_var.h>
56#include <netinet6/in6_gif.h>
57#include <netinet6/ip6.h>
58#include <netinet/ip_ecn.h>
59#include <netinet6/ip6_ecn.h>
60
61#include <net/if_gif.h>
62
63#include <net/net_osdep.h>
64
65int
66in6_gif_output(ifp, family, m, rt)
67 struct ifnet *ifp;
68 int family; /* family of the packet to be encapsulate. */
69 struct mbuf *m;
70 struct rtentry *rt;
71{
72 struct gif_softc *sc = (struct gif_softc*)ifp;

--- 23 unchanged lines hidden (view full) ---

96 if (!m)
97 return ENOBUFS;
98 }
99 ip = mtod(m, struct ip *);
100 itos = ip->ip_tos;
101 break;
102 }
103#endif
104 case AF_INET6:
105 {
106 struct ip6_hdr *ip6;
107 proto = IPPROTO_IPV6;
108 if (m->m_len < sizeof(*ip6)) {
109 m = m_pullup(m, sizeof(*ip6));
110 if (!m)
111 return ENOBUFS;
112 }
113 ip6 = mtod(m, struct ip6_hdr *);
114 itos = (ntohl(ip6->ip6_flow) >> 20) & 0xff;
115 break;
116 }
117 default:
118#ifdef DIAGNOSTIC
119 printf("in6_gif_output: warning: unknown family %d passed\n",
120 family);
121#endif
122 m_freem(m);
123 return EAFNOSUPPORT;
124 }
125
126 /* prepend new IP header */
127 M_PREPEND(m, sizeof(struct ip6_hdr), M_DONTWAIT);
128 if (m && m->m_len < sizeof(struct ip6_hdr))
129 m = m_pullup(m, sizeof(struct ip6_hdr));
130 if (m == NULL) {
131 printf("ENOBUFS in in6_gif_output %d\n", __LINE__);
132 return ENOBUFS;
133 }
134
135 ip6 = mtod(m, struct ip6_hdr *);
136 ip6->ip6_flow = 0;
137 ip6->ip6_vfc = IPV6_VERSION;
138 ip6->ip6_plen = htons((u_short)m->m_pkthdr.len);
139 ip6->ip6_nxt = proto;
140 ip6->ip6_hlim = ip6_gif_hlim;
141 ip6->ip6_src = sin6_src->sin6_addr;
142 if (ifp->if_flags & IFF_LINK0) {
143 /* multi-destination mode */
144 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))
145 ip6->ip6_dst = sin6_dst->sin6_addr;
146 else if (rt) {
147 ip6->ip6_dst = ((struct sockaddr_in6 *)(rt->rt_gateway))->sin6_addr;
148 } else {
149 m_freem(m);
150 return ENETUNREACH;
151 }
152 } else {
153 /* bidirectional configured tunnel mode */
154 if (!IN6_IS_ADDR_UNSPECIFIED(&sin6_dst->sin6_addr))

--- 15 unchanged lines hidden (view full) ---

170 bzero(dst, sizeof(*dst));
171 dst->sin6_family = sin6_dst->sin6_family;
172 dst->sin6_len = sizeof(struct sockaddr_in6);
173 dst->sin6_addr = sin6_dst->sin6_addr;
174 if (sc->gif_ro6.ro_rt) {
175 RTFREE(sc->gif_ro6.ro_rt);
176 sc->gif_ro6.ro_rt = NULL;
177 }
178 }
179
180 if (sc->gif_ro6.ro_rt == NULL) {
181 rtalloc((struct route *)&sc->gif_ro6);
182 if (sc->gif_ro6.ro_rt == NULL) {
183 m_freem(m);
184 return ENETUNREACH;
185 }
186 }
187
188 return(ip6_output(m, 0, &sc->gif_ro6, 0, 0, NULL));
189}
190
191int in6_gif_input(mp, offp, proto)
192 struct mbuf **mp;
193 int *offp, proto;
194{
195 struct mbuf *m = *mp;
196 struct gif_softc *sc;
197 struct ifnet *gifp = NULL;
198 struct ip6_hdr *ip6;
199 int i;
200 int af = 0;
201 u_int32_t otos;
202
203 ip6 = mtod(m, struct ip6_hdr *);
204
205#define satoin6(sa) (((struct sockaddr_in6 *)(sa))->sin6_addr)
206 for (i = 0, sc = gif; i < ngif; i++, sc++) {
207 if (sc->gif_psrc == NULL ||
208 sc->gif_pdst == NULL ||
209 sc->gif_psrc->sa_family != AF_INET6 ||
210 sc->gif_pdst->sa_family != AF_INET6) {
211 continue;
212 }
213 if ((sc->gif_if.if_flags & IFF_UP) == 0)
214 continue;
215 if ((sc->gif_if.if_flags & IFF_LINK0) &&
216 IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) &&
217 IN6_IS_ADDR_UNSPECIFIED(&satoin6(sc->gif_pdst))) {
218 gifp = &sc->gif_if;
219 continue;
220 }
221 if (IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_psrc), &ip6->ip6_dst) &&
222 IN6_ARE_ADDR_EQUAL(&satoin6(sc->gif_pdst), &ip6->ip6_src)) {
223 gifp = &sc->gif_if;
224 break;
225 }
226 }
227
228 if (gifp == NULL) {
229 m_freem(m);
230 ip6stat.ip6s_nogif++;
231 return IPPROTO_DONE;
232 }
233
234 otos = ip6->ip6_flow;
235 m_adj(m, *offp);
236
237 switch (proto) {
238#ifdef INET
239 case IPPROTO_IPV4:
240 {
241 struct ip *ip;

--- 6 unchanged lines hidden (view full) ---

248 return IPPROTO_DONE;
249 }
250 ip = mtod(m, struct ip *);
251 if (gifp->if_flags & IFF_LINK1)
252 ip_ecn_egress(ECN_ALLOWED, &otos8, &ip->ip_tos);
253 break;
254 }
255#endif /* INET */
256 case IPPROTO_IPV6:
257 {
258 struct ip6_hdr *ip6;
259 af = AF_INET6;
260 if (m->m_len < sizeof(*ip6)) {
261 m = m_pullup(m, sizeof(*ip6));
262 if (!m)
263 return IPPROTO_DONE;
264 }
265 ip6 = mtod(m, struct ip6_hdr *);
266 if (gifp->if_flags & IFF_LINK1)
267 ip6_ecn_egress(ECN_ALLOWED, &otos, &ip6->ip6_flow);
268 break;
269 }
270 default:
271 ip6stat.ip6s_nogif++;
272 m_freem(m);
273 return IPPROTO_DONE;
274 }
275
276 gif_input(m, af, gifp);
277 return IPPROTO_DONE;
278}