ref: 7134d62ccbb32c783de67d26907e4e856c48f29c
parent: eb6bba80ef02940161518ff65113e84385f172b1
author: aiju <devnull@localhost>
date: Wed May 31 19:41:21 EDT 2017
pc: add netconsole
--- a/sys/src/9/pc/devether.c
+++ b/sys/src/9/pc/devether.c
@@ -554,3 +554,141 @@
devremove,
etherwstat,
};
+
+enum { PktHdr = 42 };
+typedef struct Netconsole Netconsole;
+struct Netconsole {
+ char buf[512];
+ int n;
+ Lock;
+ Ether *ether;
+};
+static Netconsole *netcons;
+
+extern ushort ipcsum(uchar *);
+
+void
+netconsputc(Uart *, int c)
+{
+ char *p;
+ u16int cs;
+
+ ilock(netcons);
+ netcons->buf[netcons->n++] = c;
+ if(c != '\n' && netcons->n < sizeof(netcons->buf)){
+ iunlock(netcons);
+ return;
+ }
+ p = netcons->buf;
+ p[16] = netcons->n - 14 >> 8;
+ p[17] = netcons->n - 14;
+ p[24] = 0;
+ p[25] = 0;
+ cs = ipcsum((uchar*) p + 14);
+ p[24] = cs >> 8;
+ p[25] = cs;
+ p[38] = netcons->n - 34 >> 8;
+ p[39] = netcons->n - 34;
+ memmove(p+Eaddrlen, netcons->ether->ea, Eaddrlen);
+ qiwrite(netcons->ether->oq, p, netcons->n);
+ netcons->n = PktHdr;
+ iunlock(netcons);
+ if(netcons->ether->transmit != nil)
+ netcons->ether->transmit(netcons->ether);
+}
+
+PhysUart netconsphys = {
+ .putc = netconsputc,
+};
+Uart netconsuart = { .phys = &netconsphys };
+
+void
+netconsole(void)
+{
+ char *p;
+ char *r;
+ int i;
+ int srcport, devno, dstport;
+ u8int srcip[4], dstip[4];
+ u64int dstmac;
+ Netconsole *nc;
+
+ if((p = getconf("console")) == nil || strncmp(p, "net ", 4) != 0)
+ return;
+ p += 4;
+ for(i = 0; i < 4; i++){
+ srcip[i] = strtol(p, &r, 0);
+ p = r + 1;
+ if(i == 3) break;
+ if(*r != '.') goto err;
+ }
+ if(*r == '!'){
+ srcport = strtol(p, &r, 0);
+ p = r + 1;
+ }else
+ srcport = 6665;
+ if(*r == '/'){
+ devno = strtol(p, &r, 0);
+ p = r + 1;
+ }else
+ devno = 0;
+ if(*r != ',') goto err;
+ for(i = 0; i < 4; i++){
+ dstip[i] = strtol(p, &r, 0);
+ p = r + 1;
+ if(i == 3) break;
+ if(*r != '.') goto err;
+ }
+ if(*r == '!'){
+ dstport = strtol(p, &r, 0);
+ p = r + 1;
+ }else
+ dstport = 6666;
+ if(*r == '/'){
+ dstmac = strtoull(p, &r, 16);
+ if(r - p != 12) goto err;
+ }else
+ dstmac = ((uvlong)-1) >> 16;
+ if(*r != 0) goto err;
+
+ if(devno >= MaxEther || etherxx[devno] == nil){
+ print("netconsole: no device #l%d\n", devno);
+ return;
+ }
+
+ nc = malloc(sizeof(Netconsole));
+ if(nc == nil){
+ print("netconsole: out of memory");
+ return;
+ }
+ memset(nc, 0, sizeof(Netconsole));
+ nc->ether = etherxx[devno];
+
+ uchar header[PktHdr] = {
+ /* 0 */ dstmac >> 40, dstmac >> 32, dstmac >> 24, dstmac >> 16, dstmac >> 8, dstmac >> 0,
+ /* 6 */ 0, 0, 0, 0, 0, 0,
+ /* 12 */ 0x08, 0x00,
+ /* 14 */ 0x45, 0x00,
+ /* 16 */ 0x00, 0x00, /* total length */
+ /* 18 */ 0x00, 0x00, 0x00, 0x00,
+ /* 22 */ 64, /* ttl */
+ /* 23 */ 0x11, /* protocol */
+ /* 24 */ 0x00, 0x00, /* checksum */
+ /* 26 */ srcip[0], srcip[1], srcip[2], srcip[3],
+ /* 30 */ dstip[0], dstip[1], dstip[2], dstip[3],
+ /* 34 */ srcport >> 8, srcport, dstport >> 8, dstport,
+ /* 38 */ 0x00, 0x00, /* length */
+ /* 40 */ 0x00, 0x00 /* checksum */
+ };
+
+ memmove(nc->buf, header, PktHdr);
+ nc->n = PktHdr;
+
+ netcons = nc;
+ consuart = &netconsuart;
+ return;
+
+err:
+ print("netconsole: invalid string %#q\n", getconf("console"));
+ print("netconsole: usage: srcip[!srcport][/srcdev],dstip[!dstport][/dstmac]\n");
+}