1/*
2 * demand.c - Support routines for demand-dialling.
3 *
4 * Copyright (c) 1996-2002 Paul Mackerras. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 *
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 *
13 * 2. The name(s) of the authors of this software must not be used to
14 *    endorse or promote products derived from this software without
15 *    prior written permission.
16 *
17 * 3. Redistributions of any form whatsoever must retain the following
18 *    acknowledgment:
19 *    "This product includes software developed by Paul Mackerras
20 *     <paulus@samba.org>".
21 *
22 * THE AUTHORS OF THIS SOFTWARE DISCLAIM ALL WARRANTIES WITH REGARD TO
23 * THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
24 * AND FITNESS, IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
25 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
26 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN
27 * AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING
28 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
29 */
30
31#define RCSID	"$Id: demand.c,v 1.20 2005/08/25 12:14:18 paulus Exp $"
32
33#include <stdio.h>
34#include <stdlib.h>
35#include <string.h>
36#include <errno.h>
37#include <fcntl.h>
38#include <netdb.h>
39#include <unistd.h>
40#include <syslog.h>
41#include <sys/param.h>
42#include <sys/types.h>
43#include <sys/wait.h>
44#include <sys/time.h>
45#include <sys/resource.h>
46#include <sys/stat.h>
47#include <sys/socket.h>
48#include <netinet/in.h>
49#include <arpa/inet.h>
50#ifdef PPP_FILTER
51#include <pcap-bpf.h>
52#endif
53
54#include "pppd.h"
55#include "fsm.h"
56#include "ipcp.h"
57#include "lcp.h"
58
59static const char rcsid[] = RCSID;
60
61char *frame;
62int framelen;
63int framemax;
64int escape_flag;
65int flush_flag;
66int fcs;
67
68struct packet {
69    int length;
70    struct packet *next;
71    unsigned char data[1];
72};
73
74struct packet *pend_q;
75struct packet *pend_qtail;
76
77static int active_packet __P((unsigned char *, int));
78
79/*
80 * demand_conf - configure the interface for doing dial-on-demand.
81 */
82void
83demand_conf()
84{
85    int i;
86    struct protent *protp;
87
88/*    framemax = lcp_allowoptions[0].mru;
89    if (framemax < PPP_MRU) */
90	framemax = PPP_MRU;
91    framemax += PPP_HDRLEN + PPP_FCSLEN;
92    frame = malloc(framemax);
93    if (frame == NULL)
94	novm("demand frame");
95    framelen = 0;
96    pend_q = NULL;
97    escape_flag = 0;
98    flush_flag = 0;
99    fcs = PPP_INITFCS;
100
101    netif_set_mtu(0, MIN(lcp_allowoptions[0].mru, PPP_MRU));
102    if (ppp_send_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0
103	|| ppp_recv_config(0, PPP_MRU, (u_int32_t) 0, 0, 0) < 0)
104	    fatal("Couldn't set up demand-dialled PPP interface: %m");
105
106#ifdef PPP_FILTER
107    set_filters(&pass_filter, &active_filter);
108#endif
109
110    /*
111     * Call the demand_conf procedure for each protocol that's got one.
112     */
113    for (i = 0; (protp = protocols[i]) != NULL; ++i)
114	if (protp->enabled_flag && protp->demand_conf != NULL)
115	    if (!((*protp->demand_conf)(0)))
116		die(1);
117}
118
119
120/*
121 * demand_block - set each network protocol to block further packets.
122 */
123void
124demand_block()
125{
126    int i;
127    struct protent *protp;
128
129    for (i = 0; (protp = protocols[i]) != NULL; ++i)
130	if (protp->enabled_flag && protp->demand_conf != NULL)
131	    sifnpmode(0, protp->protocol & ~0x8000, NPMODE_QUEUE);
132    get_loop_output();
133}
134
135/*
136 * demand_discard - set each network protocol to discard packets
137 * with an error.
138 */
139void
140demand_discard()
141{
142    struct packet *pkt, *nextpkt;
143    int i;
144    struct protent *protp;
145
146    for (i = 0; (protp = protocols[i]) != NULL; ++i)
147	if (protp->enabled_flag && protp->demand_conf != NULL)
148	    sifnpmode(0, protp->protocol & ~0x8000, NPMODE_ERROR);
149    get_loop_output();
150
151    /* discard all saved packets */
152    for (pkt = pend_q; pkt != NULL; pkt = nextpkt) {
153	nextpkt = pkt->next;
154	free(pkt);
155    }
156    pend_q = NULL;
157    framelen = 0;
158    flush_flag = 0;
159    escape_flag = 0;
160    fcs = PPP_INITFCS;
161}
162
163/*
164 * demand_unblock - set each enabled network protocol to pass packets.
165 */
166void
167demand_unblock()
168{
169    int i;
170    struct protent *protp;
171
172    for (i = 0; (protp = protocols[i]) != NULL; ++i)
173	if (protp->enabled_flag && protp->demand_conf != NULL)
174	    sifnpmode(0, protp->protocol & ~0x8000, NPMODE_PASS);
175}
176
177/*
178 * FCS lookup table as calculated by genfcstab.
179 */
180static u_short fcstab[256] = {
181	0x0000,	0x1189,	0x2312,	0x329b,	0x4624,	0x57ad,	0x6536,	0x74bf,
182	0x8c48,	0x9dc1,	0xaf5a,	0xbed3,	0xca6c,	0xdbe5,	0xe97e,	0xf8f7,
183	0x1081,	0x0108,	0x3393,	0x221a,	0x56a5,	0x472c,	0x75b7,	0x643e,
184	0x9cc9,	0x8d40,	0xbfdb,	0xae52,	0xdaed,	0xcb64,	0xf9ff,	0xe876,
185	0x2102,	0x308b,	0x0210,	0x1399,	0x6726,	0x76af,	0x4434,	0x55bd,
186	0xad4a,	0xbcc3,	0x8e58,	0x9fd1,	0xeb6e,	0xfae7,	0xc87c,	0xd9f5,
187	0x3183,	0x200a,	0x1291,	0x0318,	0x77a7,	0x662e,	0x54b5,	0x453c,
188	0xbdcb,	0xac42,	0x9ed9,	0x8f50,	0xfbef,	0xea66,	0xd8fd,	0xc974,
189	0x4204,	0x538d,	0x6116,	0x709f,	0x0420,	0x15a9,	0x2732,	0x36bb,
190	0xce4c,	0xdfc5,	0xed5e,	0xfcd7,	0x8868,	0x99e1,	0xab7a,	0xbaf3,
191	0x5285,	0x430c,	0x7197,	0x601e,	0x14a1,	0x0528,	0x37b3,	0x263a,
192	0xdecd,	0xcf44,	0xfddf,	0xec56,	0x98e9,	0x8960,	0xbbfb,	0xaa72,
193	0x6306,	0x728f,	0x4014,	0x519d,	0x2522,	0x34ab,	0x0630,	0x17b9,
194	0xef4e,	0xfec7,	0xcc5c,	0xddd5,	0xa96a,	0xb8e3,	0x8a78,	0x9bf1,
195	0x7387,	0x620e,	0x5095,	0x411c,	0x35a3,	0x242a,	0x16b1,	0x0738,
196	0xffcf,	0xee46,	0xdcdd,	0xcd54,	0xb9eb,	0xa862,	0x9af9,	0x8b70,
197	0x8408,	0x9581,	0xa71a,	0xb693,	0xc22c,	0xd3a5,	0xe13e,	0xf0b7,
198	0x0840,	0x19c9,	0x2b52,	0x3adb,	0x4e64,	0x5fed,	0x6d76,	0x7cff,
199	0x9489,	0x8500,	0xb79b,	0xa612,	0xd2ad,	0xc324,	0xf1bf,	0xe036,
200	0x18c1,	0x0948,	0x3bd3,	0x2a5a,	0x5ee5,	0x4f6c,	0x7df7,	0x6c7e,
201	0xa50a,	0xb483,	0x8618,	0x9791,	0xe32e,	0xf2a7,	0xc03c,	0xd1b5,
202	0x2942,	0x38cb,	0x0a50,	0x1bd9,	0x6f66,	0x7eef,	0x4c74,	0x5dfd,
203	0xb58b,	0xa402,	0x9699,	0x8710,	0xf3af,	0xe226,	0xd0bd,	0xc134,
204	0x39c3,	0x284a,	0x1ad1,	0x0b58,	0x7fe7,	0x6e6e,	0x5cf5,	0x4d7c,
205	0xc60c,	0xd785,	0xe51e,	0xf497,	0x8028,	0x91a1,	0xa33a,	0xb2b3,
206	0x4a44,	0x5bcd,	0x6956,	0x78df,	0x0c60,	0x1de9,	0x2f72,	0x3efb,
207	0xd68d,	0xc704,	0xf59f,	0xe416,	0x90a9,	0x8120,	0xb3bb,	0xa232,
208	0x5ac5,	0x4b4c,	0x79d7,	0x685e,	0x1ce1,	0x0d68,	0x3ff3,	0x2e7a,
209	0xe70e,	0xf687,	0xc41c,	0xd595,	0xa12a,	0xb0a3,	0x8238,	0x93b1,
210	0x6b46,	0x7acf,	0x4854,	0x59dd,	0x2d62,	0x3ceb,	0x0e70,	0x1ff9,
211	0xf78f,	0xe606,	0xd49d,	0xc514,	0xb1ab,	0xa022,	0x92b9,	0x8330,
212	0x7bc7,	0x6a4e,	0x58d5,	0x495c,	0x3de3,	0x2c6a,	0x1ef1,	0x0f78
213};
214
215/*
216 * loop_chars - process characters received from the loopback.
217 * Calls loop_frame when a complete frame has been accumulated.
218 * Return value is 1 if we need to bring up the link, 0 otherwise.
219 */
220int
221loop_chars(p, n)
222    unsigned char *p;
223    int n;
224{
225    int c, rv;
226
227    rv = 0;
228
229/* check for synchronous connection... */
230
231    if ( (p[0] == 0xFF) && (p[1] == 0x03) ) {
232        rv = loop_frame(p,n);
233        return rv;
234    }
235
236    for (; n > 0; --n) {
237	c = *p++;
238	if (c == PPP_FLAG) {
239	    if (!escape_flag && !flush_flag
240		&& framelen > 2 && fcs == PPP_GOODFCS) {
241		framelen -= 2;
242		if (loop_frame((unsigned char *)frame, framelen))
243		    rv = 1;
244	    }
245	    framelen = 0;
246	    flush_flag = 0;
247	    escape_flag = 0;
248	    fcs = PPP_INITFCS;
249	    continue;
250	}
251	if (flush_flag)
252	    continue;
253	if (escape_flag) {
254	    c ^= PPP_TRANS;
255	    escape_flag = 0;
256	} else if (c == PPP_ESCAPE) {
257	    escape_flag = 1;
258	    continue;
259	}
260	if (framelen >= framemax) {
261	    flush_flag = 1;
262	    continue;
263	}
264	frame[framelen++] = c;
265	fcs = PPP_FCS(fcs, c);
266    }
267    return rv;
268}
269
270/*
271 * loop_frame - given a frame obtained from the loopback,
272 * decide whether to bring up the link or not, and, if we want
273 * to transmit this frame later, put it on the pending queue.
274 * Return value is 1 if we need to bring up the link, 0 otherwise.
275 * We assume that the kernel driver has already applied the
276 * pass_filter, so we won't get packets it rejected.
277 * We apply the active_filter to see if we want this packet to
278 * bring up the link.
279 */
280int
281loop_frame(frame, len)
282    unsigned char *frame;
283    int len;
284{
285    struct packet *pkt;
286
287    /* dbglog("from loop: %P", frame, len); */
288    if (len < PPP_HDRLEN)
289	return 0;
290    if ((PPP_PROTOCOL(frame) & 0x8000) != 0)
291	return 0;		/* shouldn't get any of these anyway */
292    if (!active_packet(frame, len))
293	return 0;
294
295    pkt = (struct packet *) malloc(sizeof(struct packet) + len);
296    if (pkt != NULL) {
297	pkt->length = len;
298	pkt->next = NULL;
299	memcpy(pkt->data, frame, len);
300	if (pend_q == NULL)
301	    pend_q = pkt;
302	else
303	    pend_qtail->next = pkt;
304	pend_qtail = pkt;
305    }
306    return 1;
307}
308
309/*
310 * demand_rexmit - Resend all those frames which we got via the
311 * loopback, now that the real serial link is up.
312 */
313void
314demand_rexmit(proto, newip)
315    int proto;
316    u_int32_t newip;
317{
318    struct packet *pkt, *prev, *nextpkt;
319    unsigned short checksum;
320    unsigned short pkt_checksum = 0;
321    unsigned iphdr;
322    struct timeval tv;
323    char cv = 0;
324    char ipstr[16];
325
326    prev = NULL;
327    pkt = pend_q;
328    pend_q = NULL;
329    tv.tv_sec = 1;
330    tv.tv_usec = 0;
331    select(0,NULL,NULL,NULL,&tv);	/* Sleep for 1 Seconds */
332    for (; pkt != NULL; pkt = nextpkt) {
333	nextpkt = pkt->next;
334	if (PPP_PROTOCOL(pkt->data) == proto) {
335            if ( (proto == PPP_IP) && newip ) {
336		/* Get old checksum */
337
338		iphdr = (pkt->data[4] & 15) << 2;
339		checksum = *((unsigned short *) (pkt->data+14));
340                if (checksum == 0xFFFF) {
341                    checksum = 0;
342                }
343
344
345                if (pkt->data[13] == 17) {
346                    pkt_checksum =  *((unsigned short *) (pkt->data+10+iphdr));
347		    if (pkt_checksum) {
348                        cv = 1;
349                        if (pkt_checksum == 0xFFFF) {
350                            pkt_checksum = 0;
351                        }
352                    }
353                    else {
354                       cv = 0;
355                    }
356                }
357
358		if (pkt->data[13] == 6) {
359		    pkt_checksum = *((unsigned short *) (pkt->data+20+iphdr));
360		    cv = 1;
361                    if (pkt_checksum == 0xFFFF) {
362                        pkt_checksum = 0;
363                    }
364		}
365
366		/* Delete old Source-IP-Address */
367                checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
368                checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
369
370		pkt_checksum -= *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
371		pkt_checksum -= *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
372
373		/* Change Source-IP-Address */
374                * ((u_int32_t *) (pkt->data + 16)) = newip;
375
376		/* Add new Source-IP-Address */
377                checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
378                checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
379
380                pkt_checksum += *((unsigned short *) (pkt->data+16)) ^ 0xFFFF;
381                pkt_checksum += *((unsigned short *) (pkt->data+18)) ^ 0xFFFF;
382
383		/* Write new checksum */
384                if (!checksum) {
385                    checksum = 0xFFFF;
386                }
387                *((unsigned short *) (pkt->data+14)) = checksum;
388		if (pkt->data[13] == 6) {
389		    *((unsigned short *) (pkt->data+20+iphdr)) = pkt_checksum;
390		}
391		if (cv && (pkt->data[13] == 17) ) {
392		    *((unsigned short *) (pkt->data+10+iphdr)) = pkt_checksum;
393		}
394
395		/* Log Packet */
396		strcpy(ipstr,inet_ntoa(*( (struct in_addr *) (pkt->data+16))));
397		if (pkt->data[13] == 1) {
398		    syslog(LOG_INFO,"Open ICMP %s -> %s\n",
399			ipstr,
400			inet_ntoa(*( (struct in_addr *) (pkt->data+20))));
401		} else {
402		    syslog(LOG_INFO,"Open %s %s:%d -> %s:%d\n",
403			pkt->data[13] == 6 ? "TCP" : "UDP",
404			ipstr,
405			ntohs(*( (short *) (pkt->data+iphdr+4))),
406			inet_ntoa(*( (struct in_addr *) (pkt->data+20))),
407			ntohs(*( (short *) (pkt->data+iphdr+6))));
408                }
409            }
410	    output(0, pkt->data, pkt->length);
411	    free(pkt);
412	} else {
413	    if (prev == NULL)
414		pend_q = pkt;
415	    else
416		prev->next = pkt;
417	    prev = pkt;
418	}
419    }
420    pend_qtail = prev;
421    if (prev != NULL)
422	prev->next = NULL;
423}
424
425/*
426 * Scan a packet to decide whether it is an "active" packet,
427 * that is, whether it is worth bringing up the link for.
428 */
429static int
430active_packet(p, len)
431    unsigned char *p;
432    int len;
433{
434    int proto, i;
435    struct protent *protp;
436
437    if (len < PPP_HDRLEN)
438	return 0;
439    proto = PPP_PROTOCOL(p);
440#ifdef PPP_FILTER
441    p[0] = 1;		/* outbound packet indicator */
442    if ((pass_filter.bf_len != 0
443	 && bpf_filter(pass_filter.bf_insns, p, len, len) == 0)
444	|| (active_filter.bf_len != 0
445	    && bpf_filter(active_filter.bf_insns, p, len, len) == 0)) {
446	p[0] = 0xff;
447	return 0;
448    }
449    p[0] = 0xff;
450#endif
451    for (i = 0; (protp = protocols[i]) != NULL; ++i) {
452	if (protp->protocol < 0xC000 && (protp->protocol & ~0x8000) == proto) {
453	    if (!protp->enabled_flag)
454		return 0;
455	    if (protp->active_pkt == NULL)
456		return 1;
457	    return (*protp->active_pkt)(p, len);
458	}
459    }
460    return 0;			/* not a supported protocol !!?? */
461}
462