static int remote_service_unregister(struct hostctrl *hc, const struct service_id *srvid, unsigned short prefix_bits) { struct ctrlmsg_register req; if (!srvid) return -1; memset(&req, 0, sizeof(req)); req.cmh.type = CTRLMSG_TYPE_UNREGISTER; req.cmh.len = htons(sizeof(req)); req.cmh.xid = ++hc->xid; req.srvid_prefix_bits = (prefix_bits > SERVICE_ID_MAX_PREFIX_BITS) ? 0 : prefix_bits; memcpy(&req.srvid, srvid, sizeof(*srvid)); //memcpy(&req.address, ipaddr, sizeof(*ipaddr)); LOG_DBG("prefix_bits=%u sizeof(req)=%zu %s\n", req.srvid_prefix_bits, sizeof(req), service_id_to_str(&req.srvid)); return message_channel_send(hc->mc, &req.cmh, sizeof(req)); }
static int local_service_generic(struct hostctrl *hc, int type, const struct service_id *srvid, unsigned short prefix_bits, unsigned int priority, unsigned int weight, const struct in_addr *ipaddr) { struct { struct ctrlmsg_service cm; struct service_info service; } req; if (!srvid) return -1; memset(&req, 0, sizeof(req)); req.cm.cmh.type = type; req.cm.cmh.xid = ++hc->xid; req.cm.cmh.len = CTRLMSG_SERVICE_NUM_LEN(1); req.cm.service[0].srvid_prefix_bits = (prefix_bits > SERVICE_ID_MAX_PREFIX_BITS) ? 0 : prefix_bits; req.cm.service[0].priority = priority; req.cm.service[0].weight = weight; memcpy(&req.cm.service[0].srvid, srvid, sizeof(*srvid)); if (ipaddr) memcpy(&req.cm.service[0].address, ipaddr, sizeof(*ipaddr)); req.cm.service[0].if_index = -1; /* strncpy(req.cm.ifname, ifname, IFNAMSIZ - 1); */ LOG_DBG("op=%d prefix_bits=%u len=%u sizeof(req)=%zu %zu %s\n", type, req.cm.service[0].srvid_prefix_bits, CTRLMSG_SERVICE_LEN(&req.cm), sizeof(req), CTRLMSG_SERVICE_NUM(&req.cm), service_id_to_str(&req.cm.service[0].srvid)); return message_channel_send(hc->mc, &req.cm, req.cm.cmh.len); }
int server(void) { int sock, backlog = 8;; struct sockaddr_sv servaddr, cliaddr; if ((sock = socket_sv(AF_SERVAL, SOCK_DGRAM, SERVAL_PROTO_UDP)) < 0) { fprintf(stderr, "error creating AF_SERVAL socket: %s\n", strerror_sv(errno)); return -1; } memset(&servaddr, 0, sizeof(servaddr)); servaddr.sv_family = AF_SERVAL; servaddr.sv_srvid.s_sid32[0] = htonl(ECHO_SERVICE_ID); set_reuse_ok(sock); if (bind_sv(sock, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0) { fprintf(stderr, "error binding socket: %s\n", strerror_sv(errno)); close_sv(sock); return -1; } printf("server: bound to service id %d\n", ECHO_SERVICE_ID); listen_sv(sock, backlog); do { socklen_t l = sizeof(cliaddr); int k = 0; printf("calling accept\n"); int fd = accept_sv(sock, (struct sockaddr *)&cliaddr, &l); if (fd < 0) { fprintf(stderr, "error accepting new conn %s\n", strerror_sv(errno)); return -1; } printf("server: recv conn from service id %s; got fd = %d\n", service_id_to_str(&cliaddr.sv_srvid), fd); do { unsigned N = 2000; char buf[N]; int n; printf("server: waiting on client request\n"); if ((n = recv_sv(fd, buf, N, 0)) < 0) { fprintf(stderr, "server: error receiving client request: %s\n", strerror_sv(errno)); break; } if (n == 0) { fprintf(stderr, "server: received EOF; " "listening for new conns\n"); break; } buf[n] = '\0'; printf("server: request (%d bytes): %s\n", n, buf); if (n > 0) { char buf2[n]; int i = 0; for (; i < n; i++) buf2[i] = toupper(buf[i]); fprintf(stderr, "server: Convert and send upcase:"); for (i = 0; i < n; i++) fprintf(stderr, "%c", buf2[i]); fprintf(stderr, "\n"); send_sv(fd, buf2, n, 0); if (strcmp(buf, "quit") == 0) break; } k++; } while (1); close_sv(fd); printf("Server listening for NEW connections\n"); } while (1); close_sv(sock); printf("Exiting\n"); return -1; }
static int client(const char *filepath, struct in_addr *srv_inetaddr, int port) { int sock, ret = EXIT_FAILURE; union { struct sockaddr_sv serval; struct sockaddr_in inet; struct sockaddr saddr; } cliaddr, srvaddr; socklen_t addrlen = 0; unsigned char digest[SHA_DIGEST_LENGTH]; unsigned short srv_inetport = (unsigned short)port; int family = AF_SERVAL; memset(&cliaddr, 0, sizeof(cliaddr)); memset(&srvaddr, 0, sizeof(srvaddr)); if (srv_inetaddr) { family = AF_INET; cliaddr.inet.sin_family = family; cliaddr.inet.sin_port = htons(6767); srvaddr.inet.sin_family = family; srvaddr.inet.sin_port = htons(srv_inetport); memcpy(&srvaddr.inet.sin_addr, srv_inetaddr, sizeof(*srv_inetaddr)); addrlen = sizeof(cliaddr.inet); } else { cliaddr.serval.sv_family = family; cliaddr.serval.sv_srvid.s_sid32[0] = htonl(getpid()); srvaddr.serval.sv_family = AF_SERVAL; memcpy(&srvaddr.serval.sv_srvid, &server_srvid, sizeof(server_srvid)); addrlen = sizeof(cliaddr.serval); /* srvaddr.sv_flags = SV_WANT_FAILOVER; */ } sock = socket_sv(family, SOCK_STREAM, 0); set_reuse_ok(sock); if (family == AF_SERVAL) { ret = bind_sv(sock, &cliaddr.saddr, addrlen); if (ret < 0) { fprintf(stderr, "error client binding socket: %s\n", strerror_sv(errno)); goto out; } } if (family == AF_INET) { char buf[18]; printf("Connecting to service %s:%u\n", inet_ntop(family, srv_inetaddr, buf, 18), srv_inetport); } else { printf("Connecting to service id %s\n", service_id_to_str(&srvaddr.serval.sv_srvid)); } ret = connect_sv(sock, &srvaddr.saddr, addrlen); if (ret < 0) { fprintf(stderr, "ERROR connecting: %s\n", strerror_sv(errno)); goto out; } #if defined(SERVAL_NATIVE) { struct { struct sockaddr_sv sv; struct sockaddr_in in; } saddr; socklen_t addrlen = sizeof(saddr.in); char ipaddr[18]; memset(&saddr, 0, sizeof(saddr)); ret = getsockname(sock, (struct sockaddr *)&saddr, &addrlen); if (ret == -1) { fprintf(stderr, "Could not get sock name : %s\n", strerror(errno)); } else { printf("sock name is %s @ %s\n", service_id_to_str(&saddr.sv.sv_srvid), inet_ntop(AF_INET, &saddr.in.sin_addr, ipaddr, 18)); } memset(&saddr, 0, sizeof(saddr)); ret = getpeername(sock, (struct sockaddr *)&saddr, &addrlen); if (ret == -1) { fprintf(stderr, "Could not get peer name : %s\n", strerror(errno)); } else { printf("peer name is %s @ %s\n", service_id_to_str(&saddr.sv.sv_srvid), inet_ntop(AF_INET, &saddr.in.sin_addr, ipaddr, 18)); } } #endif printf("Connected successfully!\n"); ret = recv_file(sock, filepath, digest); if (ret == EXIT_SUCCESS) { printf("SHA1 digest is [%s]\n", digest_to_str(digest)); } else { printf("Receive failed\n"); } out: fprintf(stderr, "Closing socket...\n"); close_sv(sock); return ret; }
static int service_parse_args(int argc, char **argv, void **result) { static struct arguments args; char *ptr, *prefix = NULL; int i, ret; memset(&args, 0, sizeof(args)); args.op = __SERVICE_OP_MAX; args.prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; args.priority = 1; args.weight = 0; if (argc < 3) return -1; for (i = 0; i < __SERVICE_OP_MAX; i++) { if (strcmp(argv[0], opnames[i].name) == 0 || strcmp(argv[0], opnames[i].long_name) == 0) { args.op = i; break; } } if (args.op == __SERVICE_OP_MAX) return -1; argc--; argv++; /* Check for hexadecimal serviceID. */ if (strcmp(argv[0], "default") == 0) { /* Do nothing, serviceID already set to zero */ } else if (argv[0][0] == '0' && argv[0][1] == 'x') { int len; argv[0] += 2; ptr = argv[0]; while (*ptr != ':' && *ptr != '\0') ptr++; if (*ptr == ':') { prefix = ptr + 1; *ptr = '\0'; } len = strlen(argv[0]); if (len > 64) len = 64; if (serval_pton(argv[0], &args.srvid) == -1) return -1; } else { unsigned long id = strtoul(argv[0], &ptr, 10); if (!((*ptr == '\0' || *ptr == ':') && argv[0] != '\0')) { fprintf(stderr, "bad service id format '%s'," " should be short integer string\n", argv[0]); return -1; } if (*ptr == ':') prefix = ++ptr; args.srvid.s_sid32[0] = ntohl(id); } if (prefix) { args.prefix_bits = strtoul(prefix, &ptr, 10); if (!(*ptr == '\0' && prefix != '\0')) { fprintf(stderr, "bad prefix string %s\n", prefix); return -1; } if (args.prefix_bits > SERVICE_ID_MAX_PREFIX_BITS || args.prefix_bits == 0) args.prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; } argc--; argv++; if (argc == 0) { fprintf(stderr, "No target IP in rule\n"); return -1; } ret = name_to_inet_addr(argv[0], &args.ipaddr1); if (ret != 1) { fprintf(stderr, "Bad IP address: '%s'\n", argv[0]); return -1; } args.ip1 = &args.ipaddr1; argc--; argv++; while (argc) { if (strcmp("priority", argv[0]) == 0) { char *ptr = NULL; if (argc < 2) { fprintf(stderr, "No priority number given\n"); return -1; } args.priority = strtoul(argv[1], &ptr, 10); if (*ptr != '\0' || argv[1][0] == '\0') { fprintf(stderr, "Bad priority %s\n", argv[1]); return -1; } argc--; argv++; } else if (strcmp("weight", argv[0]) == 0) { char *ptr = NULL; if (argc < 2) { fprintf(stderr, "No weight given\n"); return -1; } args.weight = strtoul(argv[1], &ptr, 10); if (*ptr != '\0' || argv[1][0] == '\0') { fprintf(stderr, "Bad weight %s\n", argv[1]); return -1; } argc--; argv++; } else { ret = name_to_inet_addr(argv[0], &args.ipaddr2); if (ret != 1) { fprintf(stderr, "Bad IP address: '%s'\n", argv[0]); return -1; } args.ip2 = &args.ipaddr2; } argc--; argv++; } { char buf[18]; printf("%s %s:%u %s priority=%u weight=%u\n", opnames[args.op].long_name, service_id_to_str(&args.srvid), args.prefix_bits, inet_ntop(AF_INET, &args.ipaddr1, buf, 18), args.priority, args.weight); } *result = &args; return 0; }
int main(int argc, char **argv) { int sock; const char *ipdst = "192.168.56.102"; unsigned long data = 8; ssize_t ret = 0; struct { struct sockaddr_sv sv; struct sockaddr_in in; } addr; if (argc > 1) { ipdst = argv[1]; } sock = socket_sv(AF_SERVAL, SOCK_DGRAM, 0); if (sock == -1) { fprintf(stderr, "could not create SERVAL socket: %s\n", strerror(errno)); goto out; } memset(&addr, 0, sizeof(addr)); addr.sv.sv_family = AF_SERVAL; addr.sv.sv_srvid.s_sid16[0] = htons(6); addr.in.sin_family = AF_INET; if (inet_pton(AF_INET, ipdst, &addr.in.sin_addr) != 1) { fprintf(stderr, "Bad advisory IP address %s\n", ipdst); goto out; } printf("My serviceID is \'%s\'\n", service_id_to_str(&addr.sv.sv_srvid)); ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr.sv)); if (ret == -1) { fprintf(stderr, "bind: %s\n", strerror_sv(errno)); goto out; } addr.sv.sv_srvid.s_sid16[0] = htons(7); printf("Sending to \'%s\' %s\n", service_id_to_str(&addr.sv.sv_srvid), ipdst); ret = sendto_sv(sock, &data, sizeof(data), 0, (struct sockaddr *)&addr, sizeof(addr)); if (ret == -1) { fprintf(stderr, "sendto: %s\n", strerror_sv(errno)); } out: close(sock); return ret; }
int main(int argc, char **argv) { int sock; const char *ipdst = "192.168.56.102"; unsigned long data = 10; ssize_t ret = 0; struct { struct sockaddr_sv sv; struct sockaddr_in in; } addr; if (argc > 1) { ipdst = argv[1]; } sock = socket_sv(AF_SERVAL, SOCK_DGRAM, 0); if (sock == -1) { fprintf(stderr, "could not create SERVAL socket: %s\n", strerror(errno)); goto out; } /* struct addrinfo* a = NULL; struct addrinfo hints; memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; hints.ai_flags = AI_PASSIVE; getaddrinfo(NULL, "3900", &hints, &a); struct addrinfo *res; for(res = a; res != NULL; res = res->ai_next) { struct sockaddr_in* saddr = (struct sockaddr_in*)res->ai_addr; printf("hostname: %s\n", inet_ntoa(saddr->sin_addr)); } */ memset(&addr, 0, sizeof(addr)); addr.sv.sv_family = AF_SERVAL; addr.sv.sv_srvid.s_sid16[0] = htons(6); addr.in.sin_family = AF_INET; if (inet_pton(AF_INET, ipdst, &addr.in.sin_addr) != 1) { fprintf(stderr, "Bad advisory IP address %s\n", ipdst); goto out; } printf("My serviceID is \'%s\'\n", service_id_to_str(&addr.sv.sv_srvid)); ret = bind(sock, (struct sockaddr *)&addr, sizeof(addr.sv)); if (ret == -1) { fprintf(stderr, "bind: %s\n", strerror_sv(errno)); goto out; } addr.sv.sv_srvid.s_sid32[0] = htonl(10); printf("Sending to \'%s\' %s\n", service_id_to_str(&addr.sv.sv_srvid), ipdst); ret = sendto_sv(sock, &data, sizeof(data), 0, (struct sockaddr *)&addr, sizeof(addr.sv)); if (ret == -1) { fprintf(stderr, "sendto: %s\n", strerror_sv(errno)); } out: close(sock); return ret; }
int client(char *ip) { struct sockaddr_sv srvaddr; struct sockaddr_sv cliaddr; struct sockaddr_in myaddr; struct sockaddr_in dummyaddr; int dummysize; int ret = 0; unsigned N = 2000; char sbuf[N]; char rbuf[N+1]; sock_backchannel = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (sock_backchannel == -1) { fprintf(stderr, "socket: %s\n", strerror_sv(errno)); return -1; } set_reuse_ok(sock_backchannel); memset((char *)&myaddr, 0, sizeof(myaddr)); myaddr.sin_family = AF_INET; inet_aton(ip, &myaddr.sin_addr); myaddr.sin_port = htons(BACKCHANNEL_PORT); bind(sock_backchannel, (struct sockaddr *)&myaddr, sizeof(myaddr)); bzero(&srvaddr, sizeof(srvaddr)); srvaddr.sv_family = AF_SERVAL; srvaddr.sv_srvid.s_sid32[0] = htonl(ECHO_SERVICE_ID); sock = socket_sv(AF_SERVAL, SOCK_DGRAM, SERVAL_PROTO_UDP); if (sock == -1) { fprintf(stderr, "socket: %s\n", strerror_sv(errno)); return -1; } set_reuse_ok(sock); bzero(&cliaddr, sizeof(cliaddr)); cliaddr.sv_family = AF_SERVAL; cliaddr.sv_srvid.s_sid32[0] = htonl(CLIENT_SERVICE_ID); ret = bind_sv(sock, (struct sockaddr *) &cliaddr, sizeof(cliaddr)); if (ret < 0) { fprintf(stderr, "bind: %s\n", strerror_sv(errno)); return -1; } ret = connect_sv(sock, (struct sockaddr *)&srvaddr, sizeof(srvaddr)); if (ret < 0) { fprintf(stderr, "connect: %s\n", strerror_sv(errno)); return -1; } printf("connected\n"); while (1) { sprintf(sbuf, "ping %s %d", ip, BACKCHANNEL_PORT); printf("client: sending \"%s\" to service ID %s\n", sbuf, service_id_to_str(&srvaddr.sv_srvid)); ret = sendto_sv(sock, sbuf, strlen(sbuf), 0, (struct sockaddr *)&srvaddr, sizeof(srvaddr)); if (ret < 0) { fprintf(stderr, "send failed (%s)\n", strerror_sv(errno)); break; } ret = recvfrom(sock_backchannel, rbuf, N, 0, (struct sockaddr *)&dummyaddr, &dummysize); rbuf[ret] = 0; if (ret == 0) { printf("server closed\n"); break; } else { printf("Response from server: %s\n", rbuf); if (strcmp(sbuf, "quit") == 0) break; } sleep(1); } if (close_sv(sock) < 0) fprintf(stderr, "close: %s\n", strerror_sv(errno)); return ret; }
static int server(const char *filepath, size_t send_memory_buffer_size, int family) { int sock; int backlog = 8; union { struct sockaddr_sv serval; struct sockaddr_in inet; struct sockaddr saddr; } cliaddr, srvaddr; socklen_t addrlen = 0; unsigned char digest[SHA_DIGEST_LENGTH]; int ret = EXIT_FAILURE; unsigned short srv_inetport = 49254; memset(&cliaddr, 0, sizeof(cliaddr)); memset(&srvaddr, 0, sizeof(srvaddr)); if (family == AF_INET) { cliaddr.inet.sin_family = family; srvaddr.inet.sin_family = family; srvaddr.inet.sin_addr.s_addr = INADDR_ANY; srvaddr.inet.sin_port = htons(srv_inetport); addrlen = sizeof(srvaddr.inet); } else { cliaddr.serval.sv_family = family; srvaddr.serval.sv_family = AF_SERVAL; memcpy(&srvaddr.serval.sv_srvid, &listen_srvid, sizeof(listen_srvid)); addrlen = sizeof(cliaddr.serval); } sock = socket_sv(family, SOCK_STREAM, 0); if (sock < 0) { fprintf(stderr, "error creating AF_SERVAL socket: %s\n", strerror(errno)); return EXIT_FAILURE; } set_reuse_ok(sock); ret = bind_sv(sock, &srvaddr.saddr, addrlen); if (ret < 0) { fprintf(stderr, "error binding socket: %s\n", strerror(errno)); close_sv(sock); return ret; } if (family == AF_INET) { printf("server: bound to port %u\n", srv_inetport); } else { printf("server: bound to service id %s\n", service_id_to_str(&listen_srvid)); } ret = listen_sv(sock, backlog); if (ret < 0) { fprintf(stderr, "error setting listening socket: %s\n", strerror(errno)); close_sv(sock); return ret; } while (!should_exit) { socklen_t l = addrlen; int client_sock; long offset = 0; printf("Waiting for new connections\n"); client_sock = accept_sv(sock, &cliaddr.saddr, &l); if (client_sock < 0) { fprintf(stderr, "error accepting new conn: %s\n", strerror_sv(errno)); continue; } if (family == AF_INET) { char buf[18]; printf("Connect request from %s:%u\n", inet_ntop(family, &cliaddr.inet.sin_addr, buf, 18), ntohs(cliaddr.inet.sin_port)); } else { printf("Connect req from service id %s (sock = %d)\n", service_id_to_str(&cliaddr.serval.sv_srvid), client_sock); } if (send_memory_buffer_size > 0) ret = send_memory_buffer(client_sock, send_memory_buffer_size, digest); else ret = send_file(client_sock, filepath, offset, digest); if (ret == EXIT_SUCCESS) { printf("Send successful\n"); printf("SHA1 digest is [%s]\n", digest_to_str(digest)); } else if (ret < 0) { fprintf(stderr, "Failed data transfer to client\n"); //should_exit = 1; } close_sv(client_sock); } close_sv(sock); return ret; }
int Mailbox(int sid) { int sock; struct sockaddr_sv mboxaddr, cliaddr; socklen_t addrlen = sizeof(cliaddr); if ((sock = socket_sv(AF_SERVAL, SOCK_DGRAM, SERVAL_PROTO_UDP)) < 0) { fprintf(stderr, "error creating AF_SERVAL socket: %s\n", strerror_sv(errno)); return -1; } memset(&mboxaddr, 0, sizeof(mboxaddr)); mboxaddr.sv_family = AF_SERVAL; mboxaddr.sv_srvid.s_sid32[0] = htonl(sid); set_reuse_ok(sock); if (bind_sv(sock, (struct sockaddr *)&mboxaddr, sizeof(mboxaddr)) < 0) { fprintf(stderr, "error binding socket: %s\n", strerror_sv(errno)); close_sv(sock); return -1; } printf("mailbox: bound to service id %d\n", sid); memset(&cliaddr, 0, sizeof(cliaddr)); payload p; int n; list_node_t *pl; while (1) { n = recvfrom_sv(sock, &p, sizeof(payload), 0, (struct sockaddr *)&cliaddr, &addrlen); if (n == -1) { fprintf(stderr, "recvfrom: %s\n", strerror_sv(errno)); return -1; } /* if (n == 0) { fprintf(stderr, "server: received EOF"); break; } */ printf("Received a %zd byte packet number %d type %d from \'%s\' \n", n, p.num, p.type, service_id_to_str(&cliaddr.sv_srvid)); //rbuf[n] = '\0'; if (p.type==DATA) { pl = list_node_new(&p); list_rpush(dataPackets,pl); } printf("length of buffer: %d\n", dataPackets->len); } close_sv(sock); return -1; }
static int ctrl_handle_add_service_msg(struct ctrlmsg *cm, int peer) { struct ctrlmsg_service *cmr = (struct ctrlmsg_service *)cm; unsigned int num_res = CTRLMSG_SERVICE_NUM(cmr); /* TODO - flags, etc */ unsigned int i, index = 0; int err = 0; LOG_DBG("adding %u services, msg size %u\n", num_res, CTRLMSG_SERVICE_LEN(cmr)); for (i = 0; i < num_res; i++) { struct net_device *dev = NULL; struct service_info *entry = &cmr->service[i]; unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; if (entry->type == SERVICE_RULE_FORWARD) { dev = resolve_dev(entry); if (!dev) continue; } if (entry->srvid_prefix_bits > 0) prefix_bits = entry->srvid_prefix_bits; #if defined(ENABLE_DEBUG) { char ipstr[18]; LOG_DBG("Adding service id: %s(%u) " "@ address %s, priority %u, weight %u\n", service_id_to_str(&entry->srvid), prefix_bits, inet_ntop(AF_INET, &entry->address, ipstr, sizeof(ipstr)), entry->priority, entry->weight); } #endif err = service_add(&entry->srvid, prefix_bits, entry->type, entry->srvid_flags, entry->priority, entry->weight, &entry->address, sizeof(entry->address), make_target(dev), GFP_KERNEL); if (dev) dev_put(dev); if (err > 0) { if (index < i) { /* copy it over */ memcpy(&cmr->service[index], entry, sizeof(*entry)); } index++; } else { LOG_ERR("Error adding service %s: err=%d\n", service_id_to_str(&entry->srvid), err); } } if (index == 0) { /* Just return the original request with a return value */ cm->retval = CTRLMSG_RETVAL_NOENTRY; } else { /* Return the entries added */ cm->retval = CTRLMSG_RETVAL_OK; cm->len = CTRLMSG_SERVICE_NUM_LEN(index); } ctrl_sendmsg(cm, peer, GFP_KERNEL); return 0; }
static int ctrl_handle_get_service_msg(struct ctrlmsg *cm, int peer) { struct ctrlmsg_service *cmg = (struct ctrlmsg_service *)cm; struct service_entry *se; struct service_iter iter; unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; struct target *t; LOG_DBG("getting service: %s\n", service_id_to_str(&cmg->service[0].srvid)); if (cmg->service[0].srvid_prefix_bits > 0) prefix_bits = cmg->service[0].srvid_prefix_bits; se = service_find(&cmg->service[0].srvid, prefix_bits); if (se) { struct ctrlmsg_service *cres; size_t size = CTRLMSG_SERVICE_NUM_LEN(se->count); int i = 0; cres = kmalloc(size, GFP_KERNEL); if (!cres) { service_entry_put(se); cm->retval = CTRLMSG_RETVAL_ERROR; ctrl_sendmsg(cm, peer, GFP_KERNEL); return -ENOMEM; } memset(cres, 0, size); cres->cmh.type = CTRLMSG_TYPE_GET_SERVICE; cres->cmh.len = size; cres->cmh.xid = cm->xid; cres->xid = cmg->xid; memset(&iter, 0, sizeof(iter)); service_iter_init(&iter, se, SERVICE_ITER_FORWARD); while ((t = service_iter_next(&iter)) != NULL) { struct service_info *entry = &cres->service[i++]; service_get_id(se, &entry->srvid); memcpy(&entry->address, t->dst, t->dstlen); entry->srvid_prefix_bits = service_get_prefix_bits(se); entry->srvid_flags = service_iter_get_flags(&iter); entry->weight = t->weight; entry->priority = service_iter_get_priority(&iter); #if defined(ENABLE_DEBUG) { char buf[18]; LOG_DBG("Get %s %s priority=%u weight=%u\n", service_id_to_str(&entry->srvid), inet_ntop(AF_INET, &t->dst, buf, 18), entry->priority, entry->weight); } #endif } service_iter_destroy(&iter); service_entry_put(se); if (i == 0) cres->cmh.retval = CTRLMSG_RETVAL_NOENTRY; else cres->cmh.retval = CTRLMSG_RETVAL_OK; ctrl_sendmsg(&cres->cmh, peer, GFP_KERNEL); kfree(cres); LOG_DBG("Service %s matched %u entries. msg_len=%u\n", service_id_to_str(&cmg->service[0].srvid), se->count, cres->cmh.len); } else { cmg->service[0].srvid_flags = SVSF_INVALID; cmg->cmh.retval = CTRLMSG_RETVAL_NOENTRY; ctrl_sendmsg(&cmg->cmh, peer, GFP_KERNEL); LOG_DBG("Service %s not found\n", service_id_to_str(&cmg->service[0].srvid)); } return 0; }
static int ctrl_handle_mod_service_msg(struct ctrlmsg *cm, int peer) { struct ctrlmsg_service *cmr = (struct ctrlmsg_service *)cm; unsigned int num_res = CTRLMSG_SERVICE_NUM(cmr); unsigned int i, index = 0; int err = 0; if (num_res < 2 || num_res % 2 != 0) { LOG_DBG("Not an even number of service infos\n"); return 0; } LOG_DBG("modifying %u services\n", num_res / 2); for (i = 0; i < num_res; i += 2) { struct net_device *dev; struct service_info *entry_old = &cmr->service[i]; struct service_info *entry_new = &cmr->service[i+1]; unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; if (entry_old->srvid_prefix_bits > 0) prefix_bits = entry_old->srvid_prefix_bits; #if defined(ENABLE_DEBUG) { char buf[18]; LOG_DBG("Modifying: %s flags(%i) bits(%i) %s\n", service_id_to_str(&entry_old->srvid), entry_old->srvid_flags, prefix_bits, inet_ntop(AF_INET, &entry_old->address, buf, 18)); } #endif dev = resolve_dev(entry_old); if (!dev) continue; err = service_modify(&entry_old->srvid, prefix_bits, SERVICE_RULE_FORWARD, entry_old->srvid_flags, entry_new->priority, entry_new->weight, &entry_old->address, sizeof(entry_old->address), &entry_new->address, sizeof(entry_new->address), make_target(dev)); if (err > 0) { if (index < i) { /* copy it over */ memcpy(&cmr->service[index], entry_new, sizeof(*entry_new)); } index++; } else { LOG_ERR("Could not modify service %s: %i\n", service_id_to_str(&entry_old->srvid), err); } dev_put(dev); } if (index == 0) { cm->retval = CTRLMSG_RETVAL_NOENTRY; } else { cm->retval = CTRLMSG_RETVAL_OK; cm->len = CTRLMSG_SERVICE_NUM_LEN(index); } ctrl_sendmsg(cm, peer, GFP_KERNEL); return 0; }
static int ctrl_handle_del_service_msg(struct ctrlmsg *cm, int peer) { struct ctrlmsg_service *cmr = (struct ctrlmsg_service *)cm; unsigned int num_res = CTRLMSG_SERVICE_NUM(cmr); const size_t cmsg_size = sizeof(struct ctrlmsg_service_info_stat) + sizeof(struct service_info_stat) * num_res; struct ctrlmsg_service_info_stat *cms; struct service_id null_service = { .s_sid = { 0 } }; unsigned int i = 0, index = 0; int err = 0; LOG_DBG("deleting %u services\n", num_res); cms = kmalloc(cmsg_size, GFP_KERNEL); if (!cms) { cm->retval = CTRLMSG_RETVAL_ERROR; ctrl_sendmsg(cm, peer, GFP_KERNEL); return -ENOMEM; } memset(cms, 0, cmsg_size); for (i = 0; i < num_res; i++) { struct service_info *entry = &cmr->service[i]; struct service_info_stat *stat = &cms->service[index]; struct target_stats tstat; struct service_entry *se; unsigned short prefix_bits = SERVICE_ID_MAX_PREFIX_BITS; /* We might be trying to delete the "default" entry. In that case */ if (memcmp(&entry->srvid, &null_service, sizeof(null_service)) == 0 || entry->srvid_prefix_bits > 0) prefix_bits = entry->srvid_prefix_bits; stat->service.srvid_prefix_bits = prefix_bits; se = service_find_exact(&entry->srvid, prefix_bits); if (!se) { LOG_DBG("No match for serviceID %s:(%u)\n", service_id_to_str(&entry->srvid), prefix_bits); continue; } memset(&tstat, 0, sizeof(tstat)); err = service_entry_remove_target(se, entry->type, &entry->address, sizeof(entry->address), &tstat); if (err > 0) { stat->duration_sec = tstat.duration_sec; stat->duration_nsec = tstat.duration_nsec; stat->packets_resolved = tstat.packets_resolved; stat->bytes_resolved = tstat.bytes_resolved; stat->packets_dropped = tstat.packets_dropped; stat->bytes_dropped = tstat.packets_dropped; //if (index < i) { memcpy(&stat->service, entry, sizeof(*entry)); //} LOG_DBG("Service ID %s:%u\n", service_id_to_str(&stat->service.srvid), stat->service.srvid_prefix_bits); index++; } else if (err == 0) { LOG_ERR("Could not find target for service %s\n", service_id_to_str(&entry->srvid)); } else { LOG_ERR("Could not remove service %s - err %d\n", service_id_to_str(&entry->srvid), err); } service_entry_put(se); } if (index == 0) { cm->retval = CTRLMSG_RETVAL_NOENTRY; ctrl_sendmsg(cm, peer, GFP_KERNEL); } else { cms->cmh.type = CTRLMSG_TYPE_DEL_SERVICE; cms->xid = cmr->xid; cms->cmh.xid = cm->xid; cms->cmh.retval = CTRLMSG_RETVAL_OK; cms->cmh.len = CTRLMSG_SERVICE_INFO_STAT_NUM_LEN(index); ctrl_sendmsg(&cms->cmh, peer, GFP_KERNEL); } kfree(cms); return 0; }