DF-3511 / diag.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 | /* * DF-3511 diag: dump what the kernel actually sends back for MKPEER * messages with loaded vs unloaded type names, plus kldstat deltas. */ #include <sys/param.h> #include <sys/socket.h> #include <sys/types.h> #include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <netgraph/ng_message.h> #include <netgraph/socket/ng_socket.h> #ifndef NG7_VERSION #define NG7_VERSION 8 #endif #ifndef NGF_RESP #define NGF_RESP 0x00000002 /* message is a response */ #endif struct sa_ng_big { struct sockaddr_ng sg; char pad[64]; }; static void mkpeer_msg(char *buf, size_t bufsz, const char *type, u_int32_t token) { struct ng_mesg *m = (struct ng_mesg *)buf; struct ngm_mkpeer *mkp; memset(buf, 0, bufsz); m->header.version = NG7_VERSION; m->header.typecookie = NGM_GENERIC_COOKIE; m->header.cmd = NGM_MKPEER; m->header.arglen = sizeof(struct ngm_mkpeer); m->header.token = token; mkp = (struct ngm_mkpeer *)m->data; strlcpy(mkp->type, type, sizeof(mkp->type)); strlcpy(mkp->ourhook, "o", sizeof(mkp->ourhook)); strlcpy(mkp->peerhook, "p", sizeof(mkp->peerhook)); } static void dump_responses(int cs, const char *tag) { char rb[65536]; struct sockaddr_ng from; socklen_t fromlen; int n, shown = 0; for (;;) { fromlen = sizeof(from); n = recvfrom(cs, rb, sizeof(rb), MSG_DONTWAIT, (struct sockaddr *)&from, &fromlen); if (n <= 0) break; if (shown < 3) { struct ng_mesg *m = (struct ng_mesg *)rb; if (n >= (int)sizeof(struct ng_mesg)) { int dlen = n - sizeof(struct ng_mesg); char data[64]; memset(data, 0, sizeof(data)); if (dlen > 0) { memcpy(data, m->data, (size_t)dlen > 63 ? 63 : (size_t)dlen); } printf("[%s] resp n=%d ver=%u cookie=%u cmd=%u " "flags=%u token=%x arglen=%u data='%.40s'\n", tag, n, m->header.version, m->header.typecookie, m->header.cmd, m->header.flags, m->header.token, m->header.arglen, data); } else { printf("[%s] resp n=%d (short)\n", tag, n); } shown++; } } } int main(void) { char buf[sizeof(struct ng_mesg) + sizeof(struct ngm_mkpeer)]; struct sa_ng_big sb; int cs, i; if (geteuid() != 0) { fprintf(stderr, "root only\n"); return (1); } cs = socket(AF_NETGRAPH, SOCK_DGRAM, NG_CONTROL); if (cs < 0) { perror("socket"); return (1); } /* try a sequence of type names, one send each, dump responses */ { const char *types[] = { "socket", "echo", "df3511x", "cisco", "huey", NULL }; for (i = 0; types[i]; i++) { mkpeer_msg(buf, sizeof(buf), types[i], 0x1000 + i); memset(&sb, 0, sizeof(sb)); sb.sg.sg_len = 4; sb.sg.sg_family = AF_NETGRAPH; sb.sg.sg_data[0] = '.'; sb.sg.sg_data[1] = '\0'; errno = 0; if (sendto(cs, buf, sizeof(buf), 0, (struct sockaddr *)&sb.sg, 4) < 0) printf("type=%-9s sendto FAILED errno=%d(%s)\n", types[i], errno, strerror(errno)); else printf("type=%-9s sendto ok\n", types[i]); usleep(50000); /* give cpu0 a moment */ dump_responses(cs, types[i]); } } close(cs); return (0); } |