]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/ip/netdevmedium.c
ip/tcp: only calculae mss from interface mtu when directly reachable for v6
[plan9front.git] / sys / src / 9 / ip / netdevmedium.c
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
10 static void     netdevbind(Ipifc *ifc, int argc, char **argv);
11 static void     netdevunbind(Ipifc *ifc);
12 static void     netdevbwrite(Ipifc *ifc, Block *bp, int version, uchar *ip);
13 static void     netdevread(void *a);
14
15 typedef struct  Netdevrock Netdevrock;
16 struct Netdevrock
17 {
18         Fs      *f;             /* file system we belong to */
19         Proc    *readp;         /* reading process */
20         Chan    *mchan;         /* Data channel */
21 };
22
23 Medium netdevmedium =
24 {
25 .name=          "netdev",
26 .hsize=         0,
27 .mintu= 0,
28 .maxtu= 64000,
29 .maclen=        0,
30 .bind=          netdevbind,
31 .unbind=        netdevunbind,
32 .bwrite=        netdevbwrite,
33 .unbindonclose= 0,
34 };
35
36 /*
37  *  called to bind an IP ifc to a generic network device
38  *  called with ifc qlock'd
39  */
40 static void
41 netdevbind(Ipifc *ifc, int argc, char **argv)
42 {
43         Chan *mchan;
44         Netdevrock *er;
45
46         if(argc < 2)
47                 error(Ebadarg);
48
49         mchan = namec(argv[2], Aopen, ORDWR, 0);
50
51         er = smalloc(sizeof(*er));
52         er->mchan = mchan;
53         er->f = ifc->conv->p->f;
54
55         ifc->arg = er;
56
57         kproc("netdevread", netdevread, ifc);
58 }
59
60 /*
61  *  called with ifc wlock'd
62  */
63 static void
64 netdevunbind(Ipifc *ifc)
65 {
66         Netdevrock *er = ifc->arg;
67
68         if(er->readp != nil)
69                 postnote(er->readp, 1, "unbind", 0);
70
71         /* wait for readers to die */
72         while(er->readp != nil)
73                 tsleep(&up->sleep, return0, 0, 300);
74
75         if(er->mchan != nil)
76                 cclose(er->mchan);
77
78         free(er);
79 }
80
81 /*
82  *  called by ipoput with a single block to write
83  */
84 static void
85 netdevbwrite(Ipifc *ifc, Block *bp, int, uchar*)
86 {
87         Netdevrock *er = ifc->arg;
88
89         if(BLEN(bp) < ifc->mintu)
90                 bp = adjustblock(bp, ifc->mintu);
91
92         devtab[er->mchan->type]->bwrite(er->mchan, bp, 0);
93         ifc->out++;
94 }
95
96 /*
97  *  process to read from the device
98  */
99 static void
100 netdevread(void *a)
101 {
102         Ipifc *ifc;
103         Block *bp;
104         Netdevrock *er;
105         char *argv[1];
106
107         ifc = a;
108         er = ifc->arg;
109         er->readp = up; /* hide identity under a rock for unbind */
110         if(waserror()){
111                 er->readp = nil;
112                 pexit("hangup", 1);
113         }
114         for(;;){
115                 bp = devtab[er->mchan->type]->bread(er->mchan, ifc->maxtu, 0);
116                 if(bp == nil){
117                         /*
118                          * get here if mchan is a pipe and other side hangs up
119                          * clean up this interface & get out
120 ZZZ is this a good idea?
121                          */
122                         poperror();
123                         er->readp = nil;
124                         argv[0] = "unbind";
125                         if(!waserror())
126                                 ifc->conv->p->ctl(ifc->conv, argv, 1);
127                         pexit("hangup", 1);
128                 }
129                 if(!canrlock(ifc)){
130                         freeb(bp);
131                         continue;
132                 }
133                 if(waserror()){
134                         runlock(ifc);
135                         nexterror();
136                 }
137                 ifc->in++;
138                 if(ifc->lifc == nil)
139                         freeb(bp);
140                 else
141                         ipiput4(er->f, ifc, bp);
142                 runlock(ifc);
143                 poperror();
144         }
145 }
146
147 void
148 netdevmediumlink(void)
149 {
150         addipmedium(&netdevmedium);
151 }