2 * cec — coraid ethernet console
3 * Copyright © Coraid, Inc. 2006-2008.
8 #include <ip.h> /* really! */
33 void gettingkilled(int);
36 void sethdr(Pkt *, int);
51 uchar bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
55 uchar unsetea[Eaddrlen];
57 extern int fd; /* set in netopen */
60 post(char *srv, int fd)
65 if((f = create(srv, OWRITE, 0666)) == -1)
66 sysfatal("create %s: %r", srv);
67 snprint(buf, sizeof buf, "%d", fd);
68 if(write(f, buf, strlen(buf)) != strlen(buf))
69 sysfatal("write %s: %r", srv);
81 svc = smprint("/srv/%s", s);
83 svc = smprint("%s", s);
89 switch(rfork(RFFDG|RFPROC|RFNAMEG|RFNOTEG)){
103 fprint(2, "usage: cec [-dp] [-c esc] [-e ea] [-h host] [-s shelf] "
104 "[-S srv] interface\n");
109 catch(void*, char *note)
111 if(strcmp(note, "alarm") == 0)
119 return memcmp(ea, unsetea, Eaddrlen) == 0;
123 main(int argc, char **argv)
129 srv = EARGF(usage());
132 esc = tolower(*(EARGF(usage()))) - 'a' + 1;
133 if(esc == 0 || esc >= ' ')
140 if(parseether(ea, EARGF(usage())) == -1)
145 host = EARGF(usage());
151 shelf = atoi(EARGF(usage()));
157 *argv = "/net/ether0";
161 fmtinstall('E', eipfmt);
166 fprint(2, "cec: can't netopen %s\n", *argv);
173 if(shelf == -1 && host == 0 && nilea(ea))
180 exits0("shelf not found");
182 exits0("host not found");
184 exits0("ea not found");
185 } else if(shelf != -1 || host || !nilea(ea))
203 errstr(err, sizeof err);
204 rv = strcmp(err, "interrupted") == 0;
205 errstr(err, sizeof err);
229 return p[0] << 8 | p[1];
233 tcmp(void *a, void *b)
240 d = s->major - t->major;
242 d = strcmp(s->name, t->name);
244 d = memcmp(s->ea, t->ea, Eaddrlen);
258 memset(q.dst, 0xff, Eaddrlen);
259 memset(q.src, 0, Eaddrlen);
260 q.etype = htons(Etype);
267 while((n = netget(&q, sizeof q)) >= 0){
268 if((n <= 0 && didtimeout()) || ntab == nelem(tab))
270 if(n < 60 || q.len == 0 || q.type != Toffer)
273 sh = strtok((char *)q.data, " \t");
276 if(!nilea(ea) && memcmp(ea, q.src, Eaddrlen) != 0)
278 if(shelf != -1 && atoi(sh) != shelf)
280 other = strtok(nil, "\x1");
283 if(host && strcmp(host, other) != 0)
286 memcpy(p->ea, q.src, Eaddrlen);
290 snprint(p->name, sizeof p->name, "%s", other);
293 } while (ntab == 0 && pflag);
295 fprint(2, "none found.\n");
296 exits0("none found");
298 qsort(tab, ntab, sizeof tab[0], tcmp);
306 for(i = 0; i < ntab; i++)
307 print("%2d %5d %E %s\n", i, tab[i].major, tab[i].ea, tab[i].name);
319 switch(n = read(0, buf, sizeof buf)){
339 if(i >= 0 && i < ntab)
347 sethdr(Pkt *pp, int type)
349 memmove(pp->dst, con->ea, Eaddrlen);
350 memset(pp->src, 0, Eaddrlen);
351 pp->etype = htons(Etype);
362 sethdr(&msg, Treset);
375 contag = (getpid() >> 8) ^ (getpid() & 0xff);
376 sethdr(&tpk, Tinita);
378 for(i = 0; i < 3 && rpk.type != Tinitb; i++){
381 n = netget(&rpk, 1000);
386 if(rpk.type != Tinitb)
388 sethdr(&tpk, Tinitc);
403 r = read(0, buf, sizeof buf - 1);
413 fprint(2, " (q)uit, (i)nterrupt, (.)continue\n");
418 * this is a bit too aggressive. it really needs to replace only \n\r with \n.
420 static uchar crbuf[256];
423 nocrwrite(int fd, uchar *buf, int n)
428 for(i = 0; i < n; i++)
429 if((c = buf[i]) != '\r')
437 int unacked, retries, set[2];
443 memmove(ea, con->ea, Eaddrlen);
451 if ((m = mux(set)) == 0)
454 switch (muxread(m, &spk)) {
458 if (retries-- == 0) {
459 fprint(2, "Connection timed out\n");
463 netsend(&tpk, Hdrsz + unacked);
478 if ((m = mux(set)) == 0)
484 memcpy(tpk.data, spk.data, spk.len);
489 netsend(&tpk, Hdrsz + spk.len);
492 if (memcmp(spk.src, ea, Eaddrlen) != 0 ||
493 ntohs(spk.etype) != Etype)
495 if (spk.type == Toffer &&
496 memcmp(spk.dst, bcast, Eaddrlen) != 0) {
500 if (spk.conn != contag)
506 nocrwrite(1, spk.data, spk.len);
507 memmove(spk.dst, spk.src, Eaddrlen);
508 memset(spk.src, 0, Eaddrlen);
525 fprint(2, "kbd read error\n");
540 fprint(2, "connection failed\n");