Fixes tcpackproc name's memory
[akaros.git] / kern / src / net / netdevmedium.c
1 // INFERNO
2 #include <vfs.h>
3 #include <kfs.h>
4 #include <slab.h>
5 #include <kmalloc.h>
6 #include <kref.h>
7 #include <string.h>
8 #include <stdio.h>
9 #include <assert.h>
10 #include <error.h>
11 #include <cpio.h>
12 #include <pmap.h>
13 #include <smp.h>
14 #include <ip.h>
15
16 static void netdevbind(struct Ipifc *ifc, int argc, char **argv);
17 static void netdevunbind(struct Ipifc *ifc);
18 static void netdevbwrite(struct Ipifc *ifc, struct block *bp, int version,
19                                                  uint8_t * ip);
20 static void netdevread(void *a);
21
22 typedef struct Netdevrock Netdevrock;
23 struct Netdevrock {
24         struct Fs *f;                           /* file system we belong to */
25         struct proc *readp;                     /* reading process */
26         struct chan *mchan;                     /* Data channel */
27 };
28
29 struct medium netdevmedium = {
30         .name = "netdev",
31         .hsize = 0,
32         .mintu = 0,
33         .maxtu = 64000,
34         .maclen = 0,
35         .bind = netdevbind,
36         .unbind = netdevunbind,
37         .bwrite = netdevbwrite,
38         .unbindonclose = 0,
39 };
40
41 /*
42  *  called to bind an IP ifc to a generic network device
43  *  called with ifc qlock'd
44  */
45 static void netdevbind(struct Ipifc *ifc, int argc, char **argv)
46 {
47         struct chan *mchan;
48         Netdevrock *er;
49
50         if (argc < 2)
51                 error(Ebadarg);
52
53         mchan = namec(argv[2], Aopen, ORDWR, 0);
54
55         er = kzmalloc(sizeof(*er), 0);
56         er->mchan = mchan;
57         er->f = ifc->conv->p->f;
58
59         ifc->arg = er;
60
61         ktask("netdevread", netdevread, ifc);
62 }
63
64 /*
65  *  called with ifc wlock'd
66  */
67 static void netdevunbind(struct Ipifc *ifc)
68 {
69         Netdevrock *er = ifc->arg;
70 /*
71         if(er->readp != NULL)
72                 postnote(er->readp, 1, "unbind", 0);
73 */
74         printk("%s is messed up, shouldn't track procs\n", __FUNCTION__);
75         /* wait for readers to die */
76         while (er->readp != NULL)
77                 udelay_sched(300 * 1000);
78
79         if (er->mchan != NULL)
80                 cclose(er->mchan);
81
82         kfree(er);
83 }
84
85 /*
86  *  called by ipoput with a single block to write
87  */
88 static void
89 netdevbwrite(struct Ipifc *ifc, struct block *bp, int unused_int,
90                          uint8_t * unused_uint8_p_t)
91 {
92         Netdevrock *er = ifc->arg;
93
94         if (bp->next)
95                 bp = concatblock(bp);
96         if (BLEN(bp) < ifc->mintu)
97                 bp = adjustblock(bp, ifc->mintu);
98
99         devtab[er->mchan->type].bwrite(er->mchan, bp, 0);
100         ifc->out++;
101 }
102
103 /*
104  *  process to read from the device
105  */
106 static void netdevread(void *a)
107 {
108         ERRSTACK(2);
109         struct Ipifc *ifc;
110         struct block *bp;
111         Netdevrock *er;
112         char *argv[1];
113
114         ifc = a;
115         er = ifc->arg;
116         er->readp = current;    /* hide identity under a rock for unbind */
117         if (waserror()) {
118                 er->readp = NULL;
119                 warn("netdevread returns unexpectedly");
120                 poperror();
121                 return;
122         }
123         for (;;) {
124                 bp = devtab[er->mchan->type].bread(er->mchan, ifc->maxtu, 0);
125                 if (bp == NULL) {
126                         /*
127                          * get here if mchan is a pipe and other side hangs up
128                          * clean up this interface & get out
129                          ZZZ is this a good idea?  (watch your errors btw)
130                          */
131                         poperror();
132                         er->readp = NULL;
133                         argv[0] = "unbind";
134                         if (!waserror())
135                                 ifc->conv->p->ctl(ifc->conv, argv, 1);
136                         poperror();
137                         warn("netdevread returns unexpectedly");
138                         return;
139                 }
140                 if (!canrlock(&ifc->rwlock)) {
141                         freeb(bp);
142                         continue;
143                 }
144                 if (waserror()) {
145                         runlock(&ifc->rwlock);
146                         nexterror();
147                 }
148                 ifc->in++;
149                 if (ifc->lifc == NULL)
150                         freeb(bp);
151                 else
152                         ipiput4(er->f, ifc, bp);
153                 runlock(&ifc->rwlock);
154                 poperror();
155         }
156         poperror();
157 }
158
159 void netdevmediumlink(void)
160 {
161         addipmedium(&netdevmedium);
162 }