Deleted Added
full compact
ip.c (48142) ip.c (49140)
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 * $Id: ip.c,v 1.63 1999/06/02 15:59:00 brian Exp $
20 * $Id: ip.c,v 1.64 1999/06/23 16:48:23 brian Exp $
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>

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

74 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
76};
77
78#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p))
79
80static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
81
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>

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

74 544, 513, 514, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
75 80, 81, 0, 0, 0, 21, 22, 23, 0, 0, 0, 0, 0, 0, 0, 543,
76};
77
78#define INTERACTIVE(p) (interactive_ports[(p) & 0x1F] == (p))
79
80static const char *TcpFlags[] = { "FIN", "SYN", "RST", "PSH", "ACK", "URG" };
81
82static int
82static __inline int
83PortMatch(int op, u_short pport, u_short rport)
84{
85 switch (op) {
83PortMatch(int op, u_short pport, u_short rport)
84{
85 switch (op) {
86 case OP_EQ:
86 case OP_EQ:
87 return (pport == rport);
88 case OP_GT:
89 return (pport > rport);
90 case OP_LT:
91 return (pport < rport);
92 default:
93 return (0);
94 }
95}
96
97/*
98 * Check a packet against a defined filter
87 return (pport == rport);
88 case OP_GT:
89 return (pport > rport);
90 case OP_LT:
91 return (pport < rport);
92 default:
93 return (0);
94 }
95}
96
97/*
98 * Check a packet against a defined filter
99 * Returns 0 to accept the packet, non-zero to drop the packet
100 *
101 * If filtering is enabled, the initial fragment of a datagram must
102 * contain the complete protocol header, and subsequent fragments
103 * must not attempt to over-write it.
99 */
100static int
104 */
105static int
101FilterCheck(struct ip *pip, struct filter *filter)
106FilterCheck(const struct ip *pip, const struct filter *filter)
102{
107{
103 int gotinfo, cproto, estab, syn, finrst, n, len, didname;
104 struct tcphdr *th;
105 struct udphdr *uh;
106 struct icmp *ih;
107 char *ptop;
108 u_short sport, dport;
109 struct filterent *fp = filter->rule;
108 int gotinfo; /* true if IP payload decoded */
109 int cproto; /* P_* protocol type if (gotinfo) */
110 int estab, syn, finrst; /* TCP state flags if (gotinfo) */
111 u_short sport, dport; /* src, dest port from packet if (gotinfo) */
112 int n; /* filter rule to process */
113 int len; /* bytes used in dbuff */
114 int didname; /* true if filter header printed */
115 int match; /* true if condition matched */
116 const struct filterent *fp = filter->rule;
110 char dbuff[100];
111
117 char dbuff[100];
118
112 if (fp->action) {
113 cproto = gotinfo = estab = syn = finrst = didname = 0;
114 sport = dport = 0;
115 for (n = 0; n < MAXFILTERS; n++) {
116 if (fp->action != A_NONE) {
117 /* permit fragments on in and out filter */
118 if (filter->fragok && (ntohs(pip->ip_off) & IP_OFFMASK) != 0)
119 return (A_PERMIT);
119 if (fp->f_action == A_NONE)
120 return (0); /* No rule is given. Permit this packet */
120
121
121 if (!didname)
122 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
123 didname = 1;
122 /* Deny any packet fragment that tries to over-write the header.
123 * Since we no longer have the real header available, punt on the
124 * largest normal header - 20 bytes for TCP without options, rounded
125 * up to the next possible fragment boundary. Since the smallest
126 * `legal' MTU is 576, and the smallest recommended MTU is 296, any
127 * fragmentation within this range is dubious at best */
128 len = ntohs(pip->ip_off) & IP_OFFMASK; /* fragment offset */
129 if (len > 0) { /* Not first fragment within datagram */
130 if (len < (24 >> 3)) /* don't allow fragment to over-write header */
131 return (1);
132 /* permit fragments on in and out filter */
133 return (filter->fragok);
134 }
135
136 cproto = gotinfo = estab = syn = finrst = didname = 0;
137 sport = dport = 0;
138 for (n = 0; n < MAXFILTERS; ) {
139 if (fp->f_action == A_NONE) {
140 n++;
141 fp++;
142 continue;
143 }
124
144
125 if ((pip->ip_src.s_addr & fp->src.mask.s_addr) ==
126 (fp->src.ipaddr.s_addr & fp->src.mask.s_addr) &&
127 (pip->ip_dst.s_addr & fp->dst.mask.s_addr) ==
128 (fp->dst.ipaddr.s_addr & fp->dst.mask.s_addr)) {
129 if (fp->proto) {
130 if (!gotinfo) {
131 ptop = (char *) pip + (pip->ip_hl << 2);
145 if (!didname) {
146 log_Printf(LogDEBUG, "%s filter:\n", filter->name);
147 didname = 1;
148 }
132
149
133 switch (pip->ip_p) {
134 case IPPROTO_ICMP:
135 cproto = P_ICMP;
136 ih = (struct icmp *) ptop;
137 sport = ih->icmp_type;
138 estab = syn = finrst = -1;
139 if (log_IsKept(LogDEBUG))
140 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
141 break;
142 case IPPROTO_IGMP:
143 cproto = P_IGMP;
144 estab = syn = finrst = -1;
145 sport = ntohs(0);
146 break;
147 case IPPROTO_UDP:
148 case IPPROTO_IPIP:
149 cproto = P_UDP;
150 uh = (struct udphdr *) ptop;
151 sport = ntohs(uh->uh_sport);
152 dport = ntohs(uh->uh_dport);
153 estab = syn = finrst = -1;
154 if (log_IsKept(LogDEBUG))
155 snprintf(dbuff, sizeof dbuff, "sport = %d, dport = %d",
156 sport, dport);
157 break;
158 case IPPROTO_TCP:
159 cproto = P_TCP;
160 th = (struct tcphdr *) ptop;
161 sport = ntohs(th->th_sport);
162 dport = ntohs(th->th_dport);
163 estab = (th->th_flags & TH_ACK);
164 syn = (th->th_flags & TH_SYN);
165 finrst = (th->th_flags & (TH_FIN|TH_RST));
166 if (log_IsKept(LogDEBUG)) {
167 if (!estab)
168 snprintf(dbuff, sizeof dbuff,
169 "flags = %02x, sport = %d, dport = %d",
170 th->th_flags, sport, dport);
171 else
172 *dbuff = '\0';
173 }
174 break;
175 default:
176 return (A_DENY); /* We'll block unknown type of packet */
177 }
178 if (log_IsKept(LogDEBUG)) {
179 if (estab != -1) {
180 len = strlen(dbuff);
181 snprintf(dbuff + len, sizeof dbuff - len,
182 ", estab = %d, syn = %d, finrst = %d",
183 estab, syn, finrst);
184 }
185 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
186 filter_Proto2Nam(cproto), dbuff);
187 }
188 gotinfo = 1;
150 match = 0;
151 if (!((pip->ip_src.s_addr ^ fp->f_src.ipaddr.s_addr) &
152 fp->f_src.mask.s_addr) &&
153 !((pip->ip_dst.s_addr ^ fp->f_dst.ipaddr.s_addr) &
154 fp->f_dst.mask.s_addr)) {
155 if (fp->f_proto != P_NONE) {
156 if (!gotinfo) {
157 const char *ptop = (const char *) pip + (pip->ip_hl << 2);
158 const struct tcphdr *th;
159 const struct udphdr *uh;
160 const struct icmp *ih;
161 int datalen; /* IP datagram length */
162
163 datalen = ntohs(pip->ip_len) - (pip->ip_hl << 2);
164 switch (pip->ip_p) {
165 case IPPROTO_ICMP:
166 cproto = P_ICMP;
167 if (datalen < 8) /* ICMP must be at least 8 octets */
168 return (1);
169 ih = (const struct icmp *) ptop;
170 sport = ih->icmp_type;
171 estab = syn = finrst = -1;
172 if (log_IsKept(LogDEBUG))
173 snprintf(dbuff, sizeof dbuff, "sport = %d", sport);
174 break;
175 case IPPROTO_IGMP:
176 cproto = P_IGMP;
177 if (datalen < 8) /* IGMP uses 8-octet messages */
178 return (1);
179 estab = syn = finrst = -1;
180 sport = ntohs(0);
181 break;
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';
189 }
216 }
190 if (log_IsKept(LogDEBUG)) {
191 if (fp->opt.srcop != OP_NONE) {
192 snprintf(dbuff, sizeof dbuff, ", src %s %d",
193 filter_Op2Nam(fp->opt.srcop), fp->opt.srcport);
194 len = strlen(dbuff);
195 } else
196 len = 0;
197 if (fp->opt.dstop != OP_NONE) {
198 snprintf(dbuff + len, sizeof dbuff - len,
199 ", dst %s %d", filter_Op2Nam(fp->opt.dstop),
200 fp->opt.dstport);
201 } else if (!len)
202 *dbuff = '\0';
217 break;
218 default:
219 return (1); /* We'll block unknown type of packet */
220 }
203
221
204 log_Printf(LogDEBUG, " rule = %d: Address match, "
205 "check against proto %s%s, action = %s\n",
206 n, filter_Proto2Nam(fp->proto),
207 dbuff, filter_Action2Nam(fp->action));
208 }
209
210 if (cproto == fp->proto) {
211 if ((fp->opt.srcop == OP_NONE ||
212 PortMatch(fp->opt.srcop, sport, fp->opt.srcport)) &&
213 (fp->opt.dstop == OP_NONE ||
214 PortMatch(fp->opt.dstop, dport, fp->opt.dstport)) &&
215 (fp->opt.estab == 0 || estab) &&
216 (fp->opt.syn == 0 || syn) &&
217 (fp->opt.finrst == 0 || finrst)) {
218 return (fp->action);
219 }
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);
220 }
228 }
221 } else {
222 /* Address is mached. Make a decision. */
223 log_Printf(LogDEBUG, " rule = %d: Address match, action = %s\n", n,
224 filter_Action2Nam(fp->action));
225 return (fp->action);
229 log_Printf(LogDEBUG, " Filter: proto = %s, %s\n",
230 filter_Proto2Nam(cproto), dbuff);
226 }
231 }
227 } else
228 log_Printf(LogDEBUG, " rule = %d: Address mismatch\n", n);
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;
229 }
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++;
230 fp++;
231 }
282 fp++;
283 }
232 return (A_DENY); /* No rule is mached. Deny this packet */
233 }
284 }
234 return (A_PERMIT); /* No rule is given. Permit this packet */
285 return (1); /* No rule is mached. Deny this packet */
235}
236
237#ifdef notdef
238static void
239IcmpError(struct ip *pip, int code)
240{
241 struct mbuf *bp;
242

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

359 " MSS = %d", ntohs(sp[1]));
360 loglen += strlen(logbuf + loglen);
361 }
362 }
363 }
364 break;
365 }
366
286}
287
288#ifdef notdef
289static void
290IcmpError(struct ip *pip, int code)
291{
292 struct mbuf *bp;
293

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

410 " MSS = %d", ntohs(sp[1]));
411 loglen += strlen(logbuf + loglen);
412 }
413 }
414 }
415 break;
416 }
417
367 if ((FilterCheck(pip, filter) & A_DENY)) {
418 if (FilterCheck(pip, filter)) {
368 if (logit)
369 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
370#ifdef notdef
371 if (direction == 0)
372 IcmpError(pip, pri);
373#endif
374 return (-1);
375 } else {
376 /* Check Keep Alive filter */
377 if (logit) {
419 if (logit)
420 log_Printf(LogTCPIP, "%s - BLOCKED\n", logbuf);
421#ifdef notdef
422 if (direction == 0)
423 IcmpError(pip, pri);
424#endif
425 return (-1);
426 } else {
427 /* Check Keep Alive filter */
428 if (logit) {
378 if (FilterCheck(pip, &bundle->filter.alive) & A_DENY)
429 if (FilterCheck(pip, &bundle->filter.alive))
379 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
380 else
381 log_Printf(LogTCPIP, "%s\n", logbuf);
382 }
383 return (pri);
384 }
385}
386

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

407 return NULL;
408 }
409 mbuf_Read(bp, tun.data, nb);
410
411 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
412 return NULL;
413
414 pip = (struct ip *)tun.data;
430 log_Printf(LogTCPIP, "%s - NO KEEPALIVE\n", logbuf);
431 else
432 log_Printf(LogTCPIP, "%s\n", logbuf);
433 }
434 return (pri);
435 }
436}
437

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

458 return NULL;
459 }
460 mbuf_Read(bp, tun.data, nb);
461
462 if (PacketCheck(bundle, tun.data, nb, &bundle->filter.in) < 0)
463 return NULL;
464
465 pip = (struct ip *)tun.data;
415 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
466 if (!FilterCheck(pip, &bundle->filter.alive))
416 bundle_StartIdleTimer(bundle);
417
418 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
419
420 nb += sizeof tun - sizeof tun.data;
421 nw = write(bundle->dev.fd, &tun, nb);
422 if (nw != nb) {
423 if (nw == -1)

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

486 if (ipcp->fsm.state != ST_OPENED)
487 return 0;
488
489 for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--)
490 if (queue->top) {
491 bp = mbuf_Contiguous(mbuf_Dequeue(queue));
492 cnt = mbuf_Length(bp);
493 pip = (struct ip *)MBUF_CTOP(bp);
467 bundle_StartIdleTimer(bundle);
468
469 ipcp_AddInOctets(&bundle->ncp.ipcp, nb);
470
471 nb += sizeof tun - sizeof tun.data;
472 nw = write(bundle->dev.fd, &tun, nb);
473 if (nw != nb) {
474 if (nw == -1)

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

537 if (ipcp->fsm.state != ST_OPENED)
538 return 0;
539
540 for (queue = &ipcp->Queue[PRI_FAST]; queue >= ipcp->Queue; queue--)
541 if (queue->top) {
542 bp = mbuf_Contiguous(mbuf_Dequeue(queue));
543 cnt = mbuf_Length(bp);
544 pip = (struct ip *)MBUF_CTOP(bp);
494 if (!(FilterCheck(pip, &bundle->filter.alive) & A_DENY))
545 if (!FilterCheck(pip, &bundle->filter.alive))
495 bundle_StartIdleTimer(bundle);
496 link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP);
497 ipcp_AddOutOctets(ipcp, cnt);
498 return 1;
499 }
500
501 return 0;
502}
546 bundle_StartIdleTimer(bundle);
547 link_PushPacket(l, bp, bundle, PRI_NORMAL, PROTO_IP);
548 ipcp_AddOutOctets(ipcp, cnt);
549 return 1;
550 }
551
552 return 0;
553}