xref: /inferno-os/os/ip/pppmedium.c (revision 4eb166cf184c1f102fb79e31b1465ea3e2021c39)
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "../port/error.h"
7 
8 #include "ip.h"
9 #include "kernel.h"
10 #include "ppp.h"
11 
12 static void	pppreader(void *a);
13 static void	pppbind(Ipifc *ifc, int argc, char **argv);
14 static void	pppunbind(Ipifc *ifc);
15 static void	pppbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
16 static void	deadremote(Ipifc *ifc);
17 
18 Medium pppmedium =
19 {
20 .name=	"ppp",
21 .hsize=	4,
22 .mintu=	Minmtu,
23 .maxtu=	Maxmtu,
24 .maclen=	0,
25 .bind=	pppbind,
26 .unbind=	pppunbind,
27 .bwrite=	pppbwrite,
28 .unbindonclose=	0,		/* don't unbind on last close */
29 };
30 
31 /*
32  *  called to bind an IP ifc to an ethernet device
33  *  called with ifc wlock'd
34  */
35 static void
36 pppbind(Ipifc *ifc, int argc, char **argv)
37 {
38 	PPP *ppp;
39 	Ipaddr ipaddr, remip;
40 	int mtu, framing;
41 	char *chapname, *secret;
42 
43 	if(argc < 3)
44 		error(Ebadarg);
45 
46 	ipmove(ipaddr, IPnoaddr);
47 	ipmove(remip, IPnoaddr);
48 	mtu = Defmtu;
49 	framing = 1;
50 	chapname = nil;
51 	secret = nil;
52 
53 	switch(argc){
54 	default:
55 	case 9:
56 		if(argv[8][0] != '-')
57 			secret = argv[8];
58 	case 8:
59 		if(argv[7][0] != '-')
60 			chapname = argv[7];
61 	case 7:
62 		if(argv[6][0] != '-')
63 			framing = strtoul(argv[6], 0, 0);
64 	case 6:
65 		if(argv[5][0] != '-')
66 			mtu = strtoul(argv[5], 0, 0);
67 	case 5:
68 		if(argv[4][0] != '-')
69 			parseip(remip, argv[4]);
70 	case 4:
71 		if(argv[3][0] != '-')
72 			parseip(ipaddr, argv[3]);
73 	case 3:
74 		break;
75 	}
76 
77 	ppp = smalloc(sizeof(*ppp));
78 	ppp->ifc = ifc;
79 	ppp->f = ifc->conv->p->f;
80 	ifc->arg = ppp;
81 	if(waserror()){
82 		pppunbind(ifc);
83 		nexterror();
84 	}
85 	if(pppopen(ppp, argv[2], ipaddr, remip, mtu, framing, chapname, secret) == nil)
86 		error("ppp open failed");
87 	poperror();
88 	kproc("pppreader", pppreader, ifc, KPDUPPG|KPDUPFDG);
89 }
90 
91 static void
92 pppreader(void *a)
93 {
94 	Ipifc *ifc;
95 	Block *bp;
96 	PPP *ppp;
97 
98 	ifc = a;
99 	ppp = ifc->arg;
100 	ppp->readp = up;	/* hide identity under a rock for unbind */
101 	setpri(PriHi);
102 
103 	if(waserror()){
104 		netlog(ppp->f, Logppp, "pppreader: %I: %s\n", ppp->local, up->env->errstr);
105 		ppp->readp = 0;
106 		deadremote(ifc);
107 		pexit("hangup", 1);
108 	}
109 
110 	for(;;){
111 		bp = pppread(ppp);
112 		if(bp == nil)
113 			error("hungup");
114 		if(!canrlock(ifc)){
115 			freeb(bp);
116 			continue;
117 		}
118 		if(waserror()){
119 			runlock(ifc);
120 			nexterror();
121 		}
122 		ifc->in++;
123 		if(ifc->lifc == nil)
124 			freeb(bp);
125 		else
126 			ipiput(ppp->f, ifc, bp);
127 		runlock(ifc);
128 		poperror();
129 	}
130 }
131 
132 /*
133  *  called with ifc wlock'd
134  */
135 static void
136 pppunbind(Ipifc *ifc)
137 {
138 	PPP *ppp = ifc->arg;
139 
140 	if(ppp == nil)
141 		return;
142 	if(ppp->readp)
143 		postnote(ppp->readp, 1, "unbind", 0);
144 	if(ppp->timep)
145 		postnote(ppp->timep, 1, "unbind", 0);
146 
147 	/* wait for kprocs to die */
148 	while(ppp->readp != 0 || ppp->timep != 0)
149 		tsleep(&up->sleep, return0, 0, 300);
150 
151 	pppclose(ppp);
152 	qclose(ifc->conv->eq);
153 	ifc->arg = nil;
154 }
155 
156 /*
157  *  called by ipoput with a single packet to write with ifc rlock'd
158  */
159 static void
160 pppbwrite(Ipifc *ifc, Block *bp, int, uchar*)
161 {
162 	PPP *ppp = ifc->arg;
163 
164 	pppwrite(ppp, bp);
165 	ifc->out++;
166 }
167 
168 /*
169  *	If the other end hangs up, we have to unbind the interface.  An extra
170  *	unbind (in the case where we are hanging up) won't do any harm.
171  */
172 static void
173 deadremote(Ipifc *ifc)
174 {
175 	int fd;
176 	char path[128];
177 	PPP *ppp;
178 
179 	ppp = ifc->arg;
180 	snprint(path, sizeof path, "#I%d/ipifc/%d/ctl", ppp->f->dev, ifc->conv->x);
181 	fd = kopen(path, ORDWR);
182 	if(fd < 0)
183 		return;
184 	kwrite(fd, "unbind", sizeof("unbind")-1);
185 	kclose(fd);
186 }
187 
188 void
189 pppmediumlink(void)
190 {
191 	addipmedium(&pppmedium);
192 }
193