Deleted Added
full compact
ip.c (50479) ip.c (50867)
1/*
2 * PPP IP Protocol Interface
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
1/*
2 * PPP IP Protocol Interface
3 *
4 * Written by Toshiharu OHNO (tony-o@iij.ad.jp)
5 *
6 * Copyright (C) 1993, Internet Initiative Japan, Inc. All rights reserverd.
7 *
8 * Redistribution and use in source and binary forms are permitted
9 * provided that the above copyright notice and this paragraph are
10 * duplicated in all such forms and that any documentation,
11 * advertising materials, and other materials related to such
12 * distribution and use acknowledge that the software was developed
13 * by the Internet Initiative Japan. The name of the
14 * IIJ may not be used to endorse or promote products derived
15 * from this software without specific prior written permission.
16 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
18 * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
19 *
20 * $FreeBSD: head/usr.sbin/ppp/ip.c 50479 1999-08-28 01:35:59Z peter $
20 * $FreeBSD: head/usr.sbin/ppp/ip.c 50867 1999-09-04 00:00:21Z brian $
21 *
22 * TODO:
23 * o Return ICMP message for filterd packet
24 * and optionaly record it into log.
25 */
26#include <sys/param.h>
27#if defined(__OpenBSD__) || defined(__NetBSD__)
28#include <sys/socket.h>
29#endif
30#include <netinet/in.h>
31#include <netinet/in_systm.h>
32#include <netinet/ip.h>
33#include <netinet/ip_icmp.h>
34#include <netinet/udp.h>
35#include <netinet/tcp.h>
36#include <arpa/inet.h>
37#include <sys/un.h>
38
39#include <errno.h>
40#include <stdio.h>
41#include <string.h>
42#include <termios.h>
43#include <unistd.h>
44
45#include "layer.h"
46#include "proto.h"
47#include "mbuf.h"
48#include "log.h"
49#include "defs.h"
50#include "timer.h"
51#include "fsm.h"
52#include "lqr.h"
53#include "hdlc.h"
54#include "throughput.h"
55#include "iplist.h"
56#include "slcompress.h"
57#include "ipcp.h"
58#include "filter.h"
59#include "descriptor.h"
60#include "lcp.h"
61#include "ccp.h"
62#include "link.h"
63#include "mp.h"
64#ifndef NORADIUS
65#include "radius.h"
66#endif
67#include "bundle.h"
68#include "tun.h"
69#include "ip.h"
70
21 *
22 * TODO:
23 * o Return ICMP message for filterd packet
24 * and optionaly record it into log.
25 */
26#include <sys/param.h>
27#if defined(__OpenBSD__) || defined(__NetBSD__)
28#include <sys/socket.h>
29#endif
30#include <netinet/in.h>
31#include <netinet/in_systm.h>
32#include <netinet/ip.h>
33#include <netinet/ip_icmp.h>
34#include <netinet/udp.h>
35#include <netinet/tcp.h>
36#include <arpa/inet.h>
37#include <sys/un.h>
38
39#include <errno.h>
40#include <stdio.h>
41#include <string.h>
42#include <termios.h>
43#include <unistd.h>
44
45#include "layer.h"
46#include "proto.h"
47#include "mbuf.h"
48#include "log.h"
49#include "defs.h"
50#include "timer.h"
51#include "fsm.h"
52#include "lqr.h"
53#include "hdlc.h"
54#include "throughput.h"
55#include "iplist.h"
56#include "slcompress.h"
57#include "ipcp.h"
58#include "filter.h"
59#include "descriptor.h"
60#include "lcp.h"
61#include "ccp.h"
62#include "link.h"
63#include "mp.h"
64#ifndef NORADIUS
65#include "radius.h"
66#endif
67#include "bundle.h"
68#include "tun.h"
69#include "ip.h"
70
71static const u_short interactive_ports[32] = {
72 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
73 80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
74};
75
76#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p))
77
78static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
79
80static __inline int
81PortMatch(int op, u_short pport, u_short rport)
82{
83 switch (op) {
84 case OP_EQ:
85 return (pport == rport);
86 case OP_GT:
87 return (pport > rport);
88 case OP_LT:
89 return (pport < rport);
90 default:
91 return (0);
92 }
93}
94
95/*
96 * Check a packet against a defined filter
97 * Returns 0 to accept the packet, non-zero to drop the packet
98 *
99 * If filtering is enabled, the initial fragment of a datagram must
100 * contain the complete protocol header, and subsequent fragments
101 * must not attempt to over-write it.
102 */
103static int
104FilterCheck(const struct ip *pip, const struct filter *filter)
105{
106 int gotinfo; /* true if IP payload decoded */
107 int cproto; /* P_* protocol type if (gotinfo) */
108 int estab, syn, finrst; /* TCP state flags if (gotinfo) */
109 u_short sport, dport; /* src, dest port from packet if (gotinfo) */
110 int n; /* filter rule to process */
111 int len; /* bytes used in dbuff */
112 int didname; /* true if filter header printed */
113 int match; /* true if condition matched */
114 const struct filterent *fp = filter->rule;
115 char dbuff[100];
116
117 if (fp->f_action == A_NONE)
118 return (0); /* No rule is given. Permit this packet */
119
120 /* Deny any packet fragment that tries to over-write the header.
121 * Since we no longer have the real header available, punt on the
122 * largest normal header - 20 bytes for TCP without options, rounded
123 * up to the next possible fragment boundary. Since the smallest
124 * `legal' MTU is 576, and the smallest recommended MTU is 296, any
125 * fragmentation within this range is dubious at best */
126 len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
127 if (len > 0) { /* Not first fragment within datagram */
128 if (len < (24 >> 3)) /* don't allow fragment to over-write header */
129 return (1);
130 /* permit fragments on in and out filter */
131 return (filter->fragok);
132 }
133
134 cproto = gotinfo = estab = syn = finrst = didname = 0;
135 sport = dport = 0;
136 for (n = 0; n < MAXFILTERS; ) {
137 if (fp->f_action == A_NONE) {
138 n++;
139 fp++;
140 continue;
141 }
142
143 if (!didname) {
144 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
145 didname = 1;
146 }
147
148 match = 0;
149 if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
150 fp->f_src.mask.s_addr) &&
151 !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
152 fp->f_dst.mask.s_addr)) {
153 if (fp->f_proto != P_NONE) {
154 if (!gotinfo) {
155 const char *ptop = (const char *) pip + (pip->ip_hl << 2);
156 const struct tcphdr *th;
157 const struct udphdr *uh;
158 const struct icmp *ih;
159 int datalen; /* IP datagram length */
160
161 datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
162 switch (pip->ip_p) {
163 case IPPROTO_ICMP:
164 cproto = P_ICMP;
165 if (datalen < 8) /* ICMP must be at least 8 octets */
166 return (1);
167 ih = (const struct icmp *) ptop;
168 sport = ih->icmp_type;
169 estab = syn = finrst = -1;
170 if (log_IsKept(LogDEBUG))
171 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
172 break;
173 case IPPROTO_IGMP:
174 cproto = P_IGMP;
175 if (datalen < 8) /* IGMP uses 8-octet messages */
176 return (1);
177 estab = syn = finrst = -1;
178 sport = ntohs(0);
179 break;
180#ifdef IPPROTO_OSPFIGP
181 case IPPROTO_OSPFIGP:
182 cproto = P_OSPF;
183 if (datalen < 8) /* IGMP uses 8-octet messages */
184 return (1);
185 estab = syn = finrst = -1;
186 sport = ntohs(0);
187 break;
188#endif
189 case IPPROTO_UDP:
190 case IPPROTO_IPIP:
191 cproto = P_UDP;
192 if (datalen < 8) /* UDP header is 8 octets */
193 return (1);
194 uh = (const struct udphdr *) ptop;
195 sport = ntohs(uh->uh_sport);
196 dport = ntohs(uh->uh_dport);
197 estab = syn = finrst = -1;
198 if (log_IsKept(LogDEBUG))
199 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
200 sport, dport);
201 break;
202 case IPPROTO_TCP:
203 cproto = P_TCP;
204 th = (const struct tcphdr *) ptop;
205 /* TCP headers are variable length. The following code
206 * ensures that the TCP header length isn't de-referenced if
207 * the datagram is too short
208 */
209 if (datalen < 20 || datalen < (th->th_off << 2))
210 return (1);
211 sport = ntohs(th->th_sport);
212 dport = ntohs(th->th_dport);
213 estab = (th->th_flags & TH_ACK);
214 syn = (th->th_flags & TH_SYN);
215 finrst = (th->th_flags & (TH_FIN|TH_RST));
216 if (log_IsKept(LogDEBUG)) {
217 if (!estab)
218 snprintf(dbuff, sizeof dbuff,
219 "flags = %02x, sport = %d, dport = %d",
220 th->th_flags, sport, dport);
221 else
222 *dbuff = '\0';
223 }
224 break;
225 default:
226 return (1); /* We'll block unknown type of packet */
227 }
228
229 if (log_IsKept(LogDEBUG)) {
230 if (estab != -1) {
231 len = strlen(dbuff);
232 snprintf(dbuff + len, sizeof dbuff - len,
233 ", estab = %d, syn = %d, finrst = %d",
234 estab, syn, finrst);
235 }
236 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
237 filter_Proto2Nam(cproto), dbuff);
238 }
239 gotinfo = 1;
240 }
241 if (log_IsKept(LogDEBUG)) {
242 if (fp->f_srcop != OP_NONE) {
243 snprintf(dbuff, sizeof dbuff, ", src %s %d",
244 filter_Op2Nam(fp->f_srcop), fp->f_srcport);
245 len = strlen(dbuff);
246 } else
247 len = 0;
248 if (fp->f_dstop != OP_NONE) {
249 snprintf(dbuff + len, sizeof dbuff - len,
250 ", dst %s %d", filter_Op2Nam(fp->f_dstop),
251 fp->f_dstport);
252 } else if (!len)
253 *dbuff = '\0';
254
255 log_Printf(LogDEBUG, " rule = %d: Address match, "
256 "check against proto %s%s, action = %s\n",
257 n, filter_Proto2Nam(fp->f_proto),
258 dbuff, filter_Action2Nam(fp->f_action));
259 }
260
261 if (cproto == fp->f_proto) {
262 if ((fp->f_srcop == OP_NONE ||
263 PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
264 (fp->f_dstop == OP_NONE ||
265 PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
266 (fp->f_estab == 0 || estab) &&
267 (fp->f_syn == 0 || syn) &&
268 (fp->f_finrst == 0 || finrst)) {
269 match = 1;
270 }
271 }
272 } else {
273 /* Address is matched and no protocol specified. Make a decision. */
274 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
275 filter_Action2Nam(fp->f_action));
276 match = 1;
277 }
278 } else
279 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
280
281 if (match != fp->f_invert) {
282 /* Take specified action */
283 if (fp->f_action < A_NONE)
284 fp = &filter->rule[n = fp->f_action];
285 else
286 return (fp->f_action != A_PERMIT);
287 } else {
288 n++;
289 fp++;
290 }
291 }
292 return (1); /* No rule is mached. Deny this packet */
293}
294
295#ifdef notdef
296static void
297IcmpError(struct ip *pip, int code)
298{
299 struct mbuf *bp;
300
301 if (pip->ip_p != IPPROTO_ICMP) {
302 bp = mbuf_Alloc(cnt, MB_IPIN);
303 memcpy(MBUF_CTOP(bp), ptr, cnt);
304 vj_SendFrame(bp);
305 ipcp_AddOutOctets(cnt);
306 }
307}
308#endif
309
310/*
311 * For debugging aid.
312 */
313int
314PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
315{
316 struct ip *pip;
317 struct tcphdr *th;
318 struct udphdr *uh;
319 struct icmp *icmph;
320 char *ptop;
321 int mask, len, n;
71static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
72
73static __inline int
74PortMatch(int op, u_short pport, u_short rport)
75{
76 switch (op) {
77 case OP_EQ:
78 return (pport == rport);
79 case OP_GT:
80 return (pport > rport);
81 case OP_LT:
82 return (pport < rport);
83 default:
84 return (0);
85 }
86}
87
88/*
89 * Check a packet against a defined filter
90 * Returns 0 to accept the packet, non-zero to drop the packet
91 *
92 * If filtering is enabled, the initial fragment of a datagram must
93 * contain the complete protocol header, and subsequent fragments
94 * must not attempt to over-write it.
95 */
96static int
97FilterCheck(const struct ip *pip, const struct filter *filter)
98{
99 int gotinfo; /* true if IP payload decoded */
100 int cproto; /* P_* protocol type if (gotinfo) */
101 int estab, syn, finrst; /* TCP state flags if (gotinfo) */
102 u_short sport, dport; /* src, dest port from packet if (gotinfo) */
103 int n; /* filter rule to process */
104 int len; /* bytes used in dbuff */
105 int didname; /* true if filter header printed */
106 int match; /* true if condition matched */
107 const struct filterent *fp = filter->rule;
108 char dbuff[100];
109
110 if (fp->f_action == A_NONE)
111 return (0); /* No rule is given. Permit this packet */
112
113 /* Deny any packet fragment that tries to over-write the header.
114 * Since we no longer have the real header available, punt on the
115 * largest normal header - 20 bytes for TCP without options, rounded
116 * up to the next possible fragment boundary. Since the smallest
117 * `legal' MTU is 576, and the smallest recommended MTU is 296, any
118 * fragmentation within this range is dubious at best */
119 len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
120 if (len > 0) { /* Not first fragment within datagram */
121 if (len < (24 >> 3)) /* don't allow fragment to over-write header */
122 return (1);
123 /* permit fragments on in and out filter */
124 return (filter->fragok);
125 }
126
127 cproto = gotinfo = estab = syn = finrst = didname = 0;
128 sport = dport = 0;
129 for (n = 0; n < MAXFILTERS; ) {
130 if (fp->f_action == A_NONE) {
131 n++;
132 fp++;
133 continue;
134 }
135
136 if (!didname) {
137 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
138 didname = 1;
139 }
140
141 match = 0;
142 if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
143 fp->f_src.mask.s_addr) &&
144 !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
145 fp->f_dst.mask.s_addr)) {
146 if (fp->f_proto != P_NONE) {
147 if (!gotinfo) {
148 const char *ptop = (const char *) pip + (pip->ip_hl << 2);
149 const struct tcphdr *th;
150 const struct udphdr *uh;
151 const struct icmp *ih;
152 int datalen; /* IP datagram length */
153
154 datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
155 switch (pip->ip_p) {
156 case IPPROTO_ICMP:
157 cproto = P_ICMP;
158 if (datalen < 8) /* ICMP must be at least 8 octets */
159 return (1);
160 ih = (const struct icmp *) ptop;
161 sport = ih->icmp_type;
162 estab = syn = finrst = -1;
163 if (log_IsKept(LogDEBUG))
164 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
165 break;
166 case IPPROTO_IGMP:
167 cproto = P_IGMP;
168 if (datalen < 8) /* IGMP uses 8-octet messages */
169 return (1);
170 estab = syn = finrst = -1;
171 sport = ntohs(0);
172 break;
173#ifdef IPPROTO_OSPFIGP
174 case IPPROTO_OSPFIGP:
175 cproto = P_OSPF;
176 if (datalen < 8) /* IGMP uses 8-octet messages */
177 return (1);
178 estab = syn = finrst = -1;
179 sport = ntohs(0);
180 break;
181#endif
182 case IPPROTO_UDP:
183 case IPPROTO_IPIP:
184 cproto = P_UDP;
185 if (datalen < 8) /* UDP header is 8 octets */
186 return (1);
187 uh = (const struct udphdr *) ptop;
188 sport = ntohs(uh->uh_sport);
189 dport = ntohs(uh->uh_dport);
190 estab = syn = finrst = -1;
191 if (log_IsKept(LogDEBUG))
192 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
193 sport, dport);
194 break;
195 case IPPROTO_TCP:
196 cproto = P_TCP;
197 th = (const struct tcphdr *) ptop;
198 /* TCP headers are variable length. The following code
199 * ensures that the TCP header length isn't de-referenced if
200 * the datagram is too short
201 */
202 if (datalen < 20 || datalen < (th->th_off << 2))
203 return (1);
204 sport = ntohs(th->th_sport);
205 dport = ntohs(th->th_dport);
206 estab = (th->th_flags & TH_ACK);
207 syn = (th->th_flags & TH_SYN);
208 finrst = (th->th_flags & (TH_FIN|TH_RST));
209 if (log_IsKept(LogDEBUG)) {
210 if (!estab)
211 snprintf(dbuff, sizeof dbuff,
212 "flags = %02x, sport = %d, dport = %d",
213 th->th_flags, sport, dport);
214 else
215 *dbuff = '\0';
216 }
217 break;
218 default:
219 return (1); /* We'll block unknown type of packet */
220 }
221
222 if (log_IsKept(LogDEBUG)) {
223 if (estab != -1) {
224 len = strlen(dbuff);
225 snprintf(dbuff + len, sizeof dbuff - len,
226 ", estab = %d, syn = %d, finrst = %d",
227 estab, syn, finrst);
228 }
229 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
230 filter_Proto2Nam(cproto), dbuff);
231 }
232 gotinfo = 1;
233 }
234 if (log_IsKept(LogDEBUG)) {
235 if (fp->f_srcop != OP_NONE) {
236 snprintf(dbuff, sizeof dbuff, ", src %s %d",
237 filter_Op2Nam(fp->f_srcop), fp->f_srcport);
238 len = strlen(dbuff);
239 } else
240 len = 0;
241 if (fp->f_dstop != OP_NONE) {
242 snprintf(dbuff + len, sizeof dbuff - len,
243 ", dst %s %d", filter_Op2Nam(fp->f_dstop),
244 fp->f_dstport);
245 } else if (!len)
246 *dbuff = '\0';
247
248 log_Printf(LogDEBUG, " rule = %d: Address match, "
249 "check against proto %s%s, action = %s\n",
250 n, filter_Proto2Nam(fp->f_proto),
251 dbuff, filter_Action2Nam(fp->f_action));
252 }
253
254 if (cproto == fp->f_proto) {
255 if ((fp->f_srcop == OP_NONE ||
256 PortMatch(fp->f_srcop, sport, fp->f_srcport)) &&
257 (fp->f_dstop == OP_NONE ||
258 PortMatch(fp->f_dstop, dport, fp->f_dstport)) &&
259 (fp->f_estab == 0 || estab) &&
260 (fp->f_syn == 0 || syn) &&
261 (fp->f_finrst == 0 || finrst)) {
262 match = 1;
263 }
264 }
265 } else {
266 /* Address is matched and no protocol specified. Make a decision. */
267 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
268 filter_Action2Nam(fp->f_action));
269 match = 1;
270 }
271 } else
272 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
273
274 if (match != fp->f_invert) {
275 /* Take specified action */
276 if (fp->f_action < A_NONE)
277 fp = &filter->rule[n = fp->f_action];
278 else
279 return (fp->f_action != A_PERMIT);
280 } else {
281 n++;
282 fp++;
283 }
284 }
285 return (1); /* No rule is mached. Deny this packet */
286}
287
288#ifdef notdef
289static void
290IcmpError(struct ip *pip, int code)
291{
292 struct mbuf *bp;
293
294 if (pip->ip_p != IPPROTO_ICMP) {
295 bp = mbuf_Alloc(cnt, MB_IPIN);
296 memcpy(MBUF_CTOP(bp), ptr, cnt);
297 vj_SendFrame(bp);
298 ipcp_AddOutOctets(cnt);
299 }
300}
301#endif
302
303/*
304 * For debugging aid.
305 */
306int
307PacketCheck(struct bundle *bundle, char *cp, int nb, struct filter *filter)
308{
309 struct ip *pip;
310 struct tcphdr *th;
311 struct udphdr *uh;
312 struct icmp *icmph;
313 char *ptop;
314 int mask, len, n;
322 int pri = PRI_NORMAL;
315 int pri = 0;
323 int logit, loglen;
324 char logbuf[200];
325
326 logit = log_IsKept(LogTCPIP) && filter->logok;
327 loglen = 0;
328
329 pip = (struct ip *) cp;
330
331 if (logit && loglen < sizeof logbuf) {
332 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
333 loglen += strlen(logbuf + loglen);
334 }
335 ptop = (cp + (pip->ip_hl << 2));
336
337 switch (pip->ip_p) {
338 case IPPROTO_ICMP:
339 if (logit && loglen < sizeof logbuf) {
340 icmph = (struct icmp *) ptop;
341 snprintf(logbuf + loglen, sizeof logbuf - loglen,
342 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
343 loglen += strlen(logbuf + loglen);
344 snprintf(logbuf + loglen, sizeof logbuf - loglen,
345 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
346 loglen += strlen(logbuf + loglen);
347 }
348 break;
349 case IPPROTO_UDP:
350 if (logit && loglen < sizeof logbuf) {
351 uh = (struct udphdr *) ptop;
352 snprintf(logbuf + loglen, sizeof logbuf - loglen,
353 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
354 loglen += strlen(logbuf + loglen);
355 snprintf(logbuf + loglen, sizeof logbuf - loglen,
356 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
357 loglen += strlen(logbuf + loglen);
358 }
359 break;
360#ifdef IPPROTO_OSPFIGP
361 case IPPROTO_OSPFIGP:
362 if (logit && loglen < sizeof logbuf) {
363 snprintf(logbuf + loglen, sizeof logbuf - loglen,
364 "OSPF: %s ---> ", inet_ntoa(pip->ip_src));
365 loglen += strlen(logbuf + loglen);
366 snprintf(logbuf + loglen, sizeof logbuf - loglen,
367 "%s", inet_ntoa(pip->ip_dst));
368 loglen += strlen(logbuf + loglen);
369 }
370 break;
371#endif
372 case IPPROTO_IPIP:
373 if (logit && loglen < sizeof logbuf) {
374 uh = (struct udphdr *) ptop;
375 snprintf(logbuf + loglen, sizeof logbuf - loglen,
376 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
377 loglen += strlen(logbuf + loglen);
378 snprintf(logbuf + loglen, sizeof logbuf - loglen,
379 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
380 loglen += strlen(logbuf + loglen);
381 }
382 break;
383 case IPPROTO_IGMP:
384 if (logit && loglen < sizeof logbuf) {
385 uh = (struct udphdr *) ptop;
386 snprintf(logbuf + loglen, sizeof logbuf - loglen,
387 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
388 loglen += strlen(logbuf + loglen);
389 snprintf(logbuf + loglen, sizeof logbuf - loglen,
390 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
391 loglen += strlen(logbuf + loglen);
392 }
393 break;
394 case IPPROTO_TCP:
395 th = (struct tcphdr *) ptop;
396 if (pip->ip_tos == IPTOS_LOWDELAY)
316 int logit, loglen;
317 char logbuf[200];
318
319 logit = log_IsKept(LogTCPIP) && filter->logok;
320 loglen = 0;
321
322 pip = (struct ip *) cp;
323
324 if (logit && loglen < sizeof logbuf) {
325 snprintf(logbuf + loglen, sizeof logbuf - loglen, "%s ", filter->name);
326 loglen += strlen(logbuf + loglen);
327 }
328 ptop = (cp + (pip->ip_hl << 2));
329
330 switch (pip->ip_p) {
331 case IPPROTO_ICMP:
332 if (logit && loglen < sizeof logbuf) {
333 icmph = (struct icmp *) ptop;
334 snprintf(logbuf + loglen, sizeof logbuf - loglen,
335 "ICMP: %s:%d ---> ", inet_ntoa(pip->ip_src), icmph->icmp_type);
336 loglen += strlen(logbuf + loglen);
337 snprintf(logbuf + loglen, sizeof logbuf - loglen,
338 "%s:%d", inet_ntoa(pip->ip_dst), icmph->icmp_type);
339 loglen += strlen(logbuf + loglen);
340 }
341 break;
342 case IPPROTO_UDP:
343 if (logit && loglen < sizeof logbuf) {
344 uh = (struct udphdr *) ptop;
345 snprintf(logbuf + loglen, sizeof logbuf - loglen,
346 "UDP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
347 loglen += strlen(logbuf + loglen);
348 snprintf(logbuf + loglen, sizeof logbuf - loglen,
349 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
350 loglen += strlen(logbuf + loglen);
351 }
352 break;
353#ifdef IPPROTO_OSPFIGP
354 case IPPROTO_OSPFIGP:
355 if (logit && loglen < sizeof logbuf) {
356 snprintf(logbuf + loglen, sizeof logbuf - loglen,
357 "OSPF: %s ---> ", inet_ntoa(pip->ip_src));
358 loglen += strlen(logbuf + loglen);
359 snprintf(logbuf + loglen, sizeof logbuf - loglen,
360 "%s", inet_ntoa(pip->ip_dst));
361 loglen += strlen(logbuf + loglen);
362 }
363 break;
364#endif
365 case IPPROTO_IPIP:
366 if (logit && loglen < sizeof logbuf) {
367 uh = (struct udphdr *) ptop;
368 snprintf(logbuf + loglen, sizeof logbuf - loglen,
369 "IPIP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
370 loglen += strlen(logbuf + loglen);
371 snprintf(logbuf + loglen, sizeof logbuf - loglen,
372 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
373 loglen += strlen(logbuf + loglen);
374 }
375 break;
376 case IPPROTO_IGMP:
377 if (logit && loglen < sizeof logbuf) {
378 uh = (struct udphdr *) ptop;
379 snprintf(logbuf + loglen, sizeof logbuf - loglen,
380 "IGMP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(uh->uh_sport));
381 loglen += strlen(logbuf + loglen);
382 snprintf(logbuf + loglen, sizeof logbuf - loglen,
383 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(uh->uh_dport));
384 loglen += strlen(logbuf + loglen);
385 }
386 break;
387 case IPPROTO_TCP:
388 th = (struct tcphdr *) ptop;
389 if (pip->ip_tos == IPTOS_LOWDELAY)
397 pri = PRI_FAST;
398 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0) {
399 if (INTERACTIVE(ntohs(th->th_sport)) || INTERACTIVE(ntohs(th->th_dport)))
400 pri = PRI_FAST;
401 }
390 pri++;
391 else if ((ntohs(pip->ip_off) & IP_OFFMASK) == 0 &&
392 ipcp_IsUrgentPort(&bundle->ncp.ipcp, ntohs(th->th_sport),
393 ntohs(th->th_dport)))
394 pri++;
395
402 if (logit && loglen < sizeof logbuf) {
403 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
404 snprintf(logbuf + loglen, sizeof logbuf - loglen,
405 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
406 loglen += strlen(logbuf + loglen);
407 snprintf(logbuf + loglen, sizeof logbuf - loglen,
408 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
409 loglen += strlen(logbuf + loglen);
410 n = 0;
411 for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
412 if (th->th_flags & mask) {
413 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
414 loglen += strlen(logbuf + loglen);
415 }
416 n++;
417 }
418 snprintf(logbuf + loglen, sizeof logbuf - loglen,
419 " seq:%lx ack:%lx (%d/%d)",
420 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
421 loglen += strlen(logbuf + loglen);
422 if ((th->th_flags & TH_SYN) && nb > 40) {
423 u_short *sp;
424
425 ptop += 20;
426 sp = (u_short *) ptop;
427 if (ntohs(sp[0]) == 0x0204) {
428 snprintf(logbuf + loglen, sizeof logbuf - loglen,
429 " MSS = %d", ntohs(sp[1]));
430 loglen += strlen(logbuf + loglen);
431 }
432 }
433 }
434 break;
435 }
436
437 if (FilterCheck(pip, filter)) {
438 if (logit)
439 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
440#ifdef notdef
441 if (direction == 0)
442 IcmpError(pip, pri);
443#endif
444 return (-1);
445 } else {
446 /* Check Keep Alive filter */
447 if (logit) {
448 if (FilterCheck(pip, &bundle->filter.alive))
449 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
450 else
451 log_Printf(LogTCPIP, "%s\n", logbuf);
452 }
453 return (pri);
454 }
455}
456
457struct mbuf *
458ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
459{
460 int nb, nw;
461 struct tun_data tun;
462 struct ip *pip;
463
464 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
465 log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
466 mbuf_Free(bp);
467 return NULL;
468 }
469
470 mbuf_SetType(bp, MB_IPIN);
471 tun_fill_header(tun, AF_INET);
472 nb = mbuf_Length(bp);
473 if (nb > sizeof tun.data) {
474 log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
475 l->name, nb, (int)(sizeof tun.data));
476 mbuf_Free(bp);
477 return NULL;
478 }
479 mbuf_Read(bp, tun.data, nb);
480
481 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
482 return NULL;
483
484 pip = (struct ip *)tun.data;
485 if (!FilterCheck(pip, &bundle->filter.alive))
486 bundle_StartIdleTimer(bundle);
487
488 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
489
490 nb += sizeof tun - sizeof tun.data;
491 nw = write(bundle->dev.fd, &tun, nb);
492 if (nw != nb) {
493 if (nw == -1)
494 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
495 l->name, nb, strerror(errno));
496 else
497 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
498 }
499
500 return NULL;
501}
502
503void
504ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
505{
506 struct mbuf *bp;
507
396 if (logit && loglen < sizeof logbuf) {
397 len = ntohs(pip->ip_len) - (pip->ip_hl << 2) - (th->th_off << 2);
398 snprintf(logbuf + loglen, sizeof logbuf - loglen,
399 "TCP: %s:%d ---> ", inet_ntoa(pip->ip_src), ntohs(th->th_sport));
400 loglen += strlen(logbuf + loglen);
401 snprintf(logbuf + loglen, sizeof logbuf - loglen,
402 "%s:%d", inet_ntoa(pip->ip_dst), ntohs(th->th_dport));
403 loglen += strlen(logbuf + loglen);
404 n = 0;
405 for (mask = TH_FIN; mask != 0x40; mask <<= 1) {
406 if (th->th_flags & mask) {
407 snprintf(logbuf + loglen, sizeof logbuf - loglen, " %s", TcpFlags[n]);
408 loglen += strlen(logbuf + loglen);
409 }
410 n++;
411 }
412 snprintf(logbuf + loglen, sizeof logbuf - loglen,
413 " seq:%lx ack:%lx (%d/%d)",
414 (u_long)ntohl(th->th_seq), (u_long)ntohl(th->th_ack), len, nb);
415 loglen += strlen(logbuf + loglen);
416 if ((th->th_flags & TH_SYN) && nb > 40) {
417 u_short *sp;
418
419 ptop += 20;
420 sp = (u_short *) ptop;
421 if (ntohs(sp[0]) == 0x0204) {
422 snprintf(logbuf + loglen, sizeof logbuf - loglen,
423 " MSS = %d", ntohs(sp[1]));
424 loglen += strlen(logbuf + loglen);
425 }
426 }
427 }
428 break;
429 }
430
431 if (FilterCheck(pip, filter)) {
432 if (logit)
433 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
434#ifdef notdef
435 if (direction == 0)
436 IcmpError(pip, pri);
437#endif
438 return (-1);
439 } else {
440 /* Check Keep Alive filter */
441 if (logit) {
442 if (FilterCheck(pip, &bundle->filter.alive))
443 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
444 else
445 log_Printf(LogTCPIP, "%s\n", logbuf);
446 }
447 return (pri);
448 }
449}
450
451struct mbuf *
452ip_Input(struct bundle *bundle, struct link *l, struct mbuf *bp)
453{
454 int nb, nw;
455 struct tun_data tun;
456 struct ip *pip;
457
458 if (bundle->ncp.ipcp.fsm.state != ST_OPENED) {
459 log_Printf(LogWARN, "ip_Input: IPCP not open - packet dropped\n");
460 mbuf_Free(bp);
461 return NULL;
462 }
463
464 mbuf_SetType(bp, MB_IPIN);
465 tun_fill_header(tun, AF_INET);
466 nb = mbuf_Length(bp);
467 if (nb > sizeof tun.data) {
468 log_Printf(LogWARN, "ip_Input: %s: Packet too large (got %d, max %d)\n",
469 l->name, nb, (int)(sizeof tun.data));
470 mbuf_Free(bp);
471 return NULL;
472 }
473 mbuf_Read(bp, tun.data, nb);
474
475 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
476 return NULL;
477
478 pip = (struct ip *)tun.data;
479 if (!FilterCheck(pip, &bundle->filter.alive))
480 bundle_StartIdleTimer(bundle);
481
482 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
483
484 nb += sizeof tun - sizeof tun.data;
485 nw = write(bundle->dev.fd, &tun, nb);
486 if (nw != nb) {
487 if (nw == -1)
488 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %s\n",
489 l->name, nb, strerror(errno));
490 else
491 log_Printf(LogERROR, "ip_Input: %s: wrote %d, got %d\n", l->name, nb, nw);
492 }
493
494 return NULL;
495}
496
497void
498ip_Enqueue(struct ipcp *ipcp, int pri, char *ptr, int count)
499{
500 struct mbuf *bp;
501
508 if (pri < 0 || pri > sizeof ipcp->Queue / sizeof ipcp->Queue[0])
502 if (pri < 0 || pri >= IPCP_QUEUES(ipcp))
509 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
510 else {
511 /*
512 * We allocate an extra 6 bytes, four at the front and two at the end.
513 * This is an optimisation so that we need to do less work in
514 * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and
515 * appending in hdlc_LayerPush().
516 */
517 bp = mbuf_Alloc(count + 6, MB_IPOUT);
518 bp->offset += 4;
519 bp->cnt -= 6;
520 memcpy(MBUF_CTOP(bp), ptr, count);
503 log_Printf(LogERROR, "Can't store in ip queue %d\n", pri);
504 else {
505 /*
506 * We allocate an extra 6 bytes, four at the front and two at the end.
507 * This is an optimisation so that we need to do less work in
508 * mbuf_Prepend() in acf_LayerPush() and proto_LayerPush() and
509 * appending in hdlc_LayerPush().
510 */
511 bp = mbuf_Alloc(count + 6, MB_IPOUT);
512 bp->offset += 4;
513 bp->cnt -= 6;
514 memcpy(MBUF_CTOP(bp), ptr, count);
521 mbuf_Enqueue(&ipcp->Queue[pri], bp);
515 mbuf_Enqueue(ipcp->Queue + pri, bp);
522 }
523}
524
525void
526ip_DeleteQueue(struct ipcp *ipcp)
527{
528 struct mqueue *queue;
529
516 }
517}
518
519void
520ip_DeleteQueue(struct ipcp *ipcp)
521{
522 struct mqueue *queue;
523
530 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
524 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
531 while (queue->top)
532 mbuf_Free(mbuf_Dequeue(queue));
533}
534
535int
536ip_QueueLen(struct ipcp *ipcp)
537{
538 struct mqueue *queue;
539 int result = 0;
540
525 while (queue->top)
526 mbuf_Free(mbuf_Dequeue(queue));
527}
528
529int
530ip_QueueLen(struct ipcp *ipcp)
531{
532 struct mqueue *queue;
533 int result = 0;
534
541 for (queue = ipcp->Queue; queue < ipcp->Queue + PRI_MAX; queue++)
535 for (queue = ipcp->Queue; queue < ipcp->Queue + IPCP_QUEUES(ipcp); queue++)
542 result += queue->qlen;
543
544 return result;
545}
546
547int
548ip_PushPacket(struct link *l, struct bundle *bundle)
549{
550 struct ipcp *ipcp = &bundle->ncp.ipcp;
551 struct mqueue *queue;
552 struct mbuf *bp;
553 struct ip *pip;
554 int cnt;
555
556 if (ipcp->fsm.state != ST_OPENED)
557 return 0;
558
536 result += queue->qlen;
537
538 return result;
539}
540
541int
542ip_PushPacket(struct link *l, struct bundle *bundle)
543{
544 struct ipcp *ipcp = &bundle->ncp.ipcp;
545 struct mqueue *queue;
546 struct mbuf *bp;
547 struct ip *pip;
548 int cnt;
549
550 if (ipcp->fsm.state != ST_OPENED)
551 return 0;
552
559 for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--)
553 queue = ipcp->Queue + IPCP_QUEUES(ipcp) - 1;
554 do {
560 if (queue->top) {
561 bp = mbuf_Contiguous(mbuf_Dequeue(queue));
562 cnt = mbuf_Length(bp);
563 pip = (struct ip *)MBUF_CTOP(bp);
564 if (!FilterCheck(pip, &bundle->filter.alive))
565 bundle_StartIdleTimer(bundle);
555 if (queue->top) {
556 bp = mbuf_Contiguous(mbuf_Dequeue(queue));
557 cnt = mbuf_Length(bp);
558 pip = (struct ip *)MBUF_CTOP(bp);
559 if (!FilterCheck(pip, &bundle->filter.alive))
560 bundle_StartIdleTimer(bundle);
566 link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP);
561 link_PushPacket(l, bp, bundle, 0, PROTO_IP);
567 ipcp_AddOutOctets(ipcp, cnt);
568 return 1;
569 }
562 ipcp_AddOutOctets(ipcp, cnt);
563 return 1;
564 }
565 } while (queue-- != ipcp->Queue);
570
571 return 0;
572}
566
567 return 0;
568}