void aoead(int fd) // advertise the virtual blade { uchar buf[2000]; Conf *p; int i; p = (Conf *)buf; memset(p, 0, sizeof *p); memset(p->h.dst, 0xff, 6); memmove(p->h.src, mac, 6); p->h.type = htons(0x88a2); p->h.flags = Resp; p->h.maj = htons(shelf); p->h.min = slot; p->h.cmd = Config; p->bufcnt = htons(bufcnt); p->scnt = maxscnt = (getmtu(sfd, ifname) - sizeof (Ata)) / 512; p->firmware = htons(FWV); p->vercmd = 0x10 | Qread; memcpy(p->data, config, nconfig); p->len = htons(nconfig); if (nmasks == 0) if (putpkt(fd, buf, sizeof *p - sizeof p->data + nconfig) == -1) { perror("putpkt aoe id"); return; } for (i=0; i<nmasks; i++) { memcpy(p->h.dst, &masks[i*Alen], Alen); if (putpkt(fd, buf, sizeof *p - sizeof p->data + nconfig) == -1) perror("putpkt aoe id"); } }
int confcmd(Conf *p, int payload) // process conf request { int len; len = ntohs(p->len); if (QCMD(p) != Qread) if (len > Nconfig || len > payload) return 0; // if you can't play nice ... switch (QCMD(p)) { case Qtest: if (len != nconfig) return 0; // fall thru case Qprefix: if (len > nconfig) return 0; if (memcmp(config, p->data, len)) return 0; // fall thru case Qread: break; case Qset: if (nconfig) if (nconfig != len || memcmp(config, p->data, len)) { p->h.flags |= Error; p->h.error = ConfigErr; break; } // fall thru case Qfset: nconfig = len; memcpy(config, p->data, nconfig); break; default: p->h.flags |= Error; p->h.error = BadArg; } memmove(p->data, config, nconfig); p->len = htons(nconfig); p->bufcnt = htons(bufcnt); p->scnt = maxscnt = (getmtu(sfd, ifname) - sizeof (Ata)) / 512; p->firmware = htons(FWV); p->vercmd = 0x10 | QCMD(p); // aoe v.1 return nconfig + sizeof *p - sizeof p->data; }
int dial(char *eth, int bufcnt) // get us a raw connection to an interface { int i, n, s; struct sockaddr_ll sa; enum { aoe_type = 0x88a2 }; memset(&sa, 0, sizeof sa); s = socket(PF_PACKET, SOCK_RAW, htons(aoe_type)); if (s == -1) { perror("got bad socket"); return -1; } i = getindx(s, eth); sa.sll_family = AF_PACKET; sa.sll_protocol = htons(0x88a2); sa.sll_ifindex = i; n = bind(s, (struct sockaddr *)&sa, sizeof sa); if (n == -1) { perror("bind funky"); return -1; } struct bpf_program { ulong bf_len; void *bf_insns; } *bpf_program = create_bpf_program(shelf, slot); setsockopt(s, SOL_SOCKET, SO_ATTACH_FILTER, bpf_program, sizeof(*bpf_program)); free_bpf_program(bpf_program); n = bufcnt * getmtu(s, eth); if (setsockopt(s, SOL_SOCKET, SO_SNDBUF, &n, sizeof(n)) < 0) perror("setsockopt SOL_SOCKET, SO_SNDBUF"); if (setsockopt(s, SOL_SOCKET, SO_RCVBUF, &n, sizeof(n)) < 0) perror("setsockopt SOL_SOCKET, SO_RCVBUF"); return s; }
/*thread que recebe da camada de baixo*/ PRIVATE void *internalsend(void *param) { int isfragmentable; int mtu; uint16_t count_id = 0; wait_list_item_t intern_list_cons; offsetlst_t *head = NULL,*aux; datagram_t *data_send = ALLOC(datagram_t, sizeof(datagram_t)); byte *buffer; while(TRUE) { intern_list_cons = wait_list_remove(); //getmtu do destino mtu = getmtu(num_global, intern_list_cons.first_dest_link); //protocolo = 1 utilizado pelo transp ou protocolo = 0 utilizado pela tab de rotas if(intern_list_cons.protocol == 1 || intern_list_cons.protocol == 0) { isfragmentable = fragpack(&head,intern_list_cons.data,intern_list_cons.size,mtu,intern_list_cons.offset); LOG("dest1 %d", intern_list_cons.dest); //sabe que é apenas dados if(isfragmentable == 0) { //nao precisou fragmentar data_send->size = intern_list_cons.size; data_send->id = count_id; data_send->frag = intern_list_cons.offset; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, data_send->size); memcpy(data_send->data, intern_list_cons.data, data_send->size); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); if(count_id <= 65535) count_id++; else count_id = 0; LOG("enviando para enlace"); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //free(data_send); ??? } else {LOG("frag para enlace"); while(head != NULL) {LOG("head para enlace"); //precisa fragmentar data_send->size = head->datagram->size; data_send->id = count_id; data_send->frag = head->datagram->frag; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; LOG("dest %d", data_send->dest); data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, head->datagram->size); memcpy(data_send->data, head->datagram->data, head->datagram->size); LOG("enviando data %s", data_send->data); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //anda com a lista aux = head; head = head->next; free(aux); } LOG("fim para enlace"); if(count_id <= 65535) count_id++; else count_id = 0; } } //protocolo = 2 , utilizado pelo repasse else { if(intern_list_cons.protocol == 2) { isfragmentable = fragpack2(&head,intern_list_cons.data,intern_list_cons.size,mtu,intern_list_cons.offset); if(isfragmentable == 0) { //nao precisou fragmentar data_send->size = intern_list_cons.size; data_send->id = intern_list_cons.id; data_send->frag = intern_list_cons.offset; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, data_send->size); memcpy(data_send->data, intern_list_cons.data, data_send->size); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); LOG("enviando para enlace"); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //free(data_send); ??? } else { while(head != NULL) { //precisa fragmentar data_send->size = head->datagram->size; data_send->id = intern_list_cons.id; data_send->frag = head->datagram->frag; data_send->protocol = intern_list_cons.protocol; data_send->ttl = intern_list_cons.ttl; data_send->dest = intern_list_cons.dest; data_send->src = intern_list_cons.src; data_send->data = ALLOC(byte, head->datagram->size); memcpy(data_send->data, head->datagram->data, head->datagram->size); buffer = ALLOC(byte, data_send->size + NET_HEADER_SIZE); buildsenddatagram(buffer,data_send); free(data_send->data); link_send(intern_list_cons.first_dest_link, buffer, data_send->size + NET_HEADER_SIZE); //anda com a lista aux = head; head = head->next; free(aux); } } } } } }