/* * net.c - network stuff for the server * Copyright (C) 2006 Thorsten Zitterell */ #include #include #include #include #include #include #include #include #include #define DNBD_USERSPACE 1 #include "../common/dnbd-cliserv.h" #include "net.h" struct listener_s { pthread_t tid; net_request_t *request; }; typedef struct listener_s listener_t; listener_t listener; /* * function net_tx(): send a server reply */ void net_tx(net_info_t * net_info, net_reply_t * reply) { if (sendto (net_info->sock, reply->data, reply->len, 0, (struct sockaddr *) &net_info->groupnet, sizeof(net_info->groupnet)) < 0) fprintf(stderr, "net_tx: mcast sendproblem\n"); } /* * function net_rx(): receive a client request * returns: 1 on correct size of reply, otherwise 0 */ int net_rx(net_info_t * net_info, net_request_t * request) { ssize_t n; request->clientlen = sizeof(request->client); n = recvfrom(net_info->sock, &request->data, sizeof(request->data), 0, &request->client, &request->clientlen); /* sizeof of request must be size of a DNBD request */ return (n == sizeof(request->data) ? 1 : 0); } /* * function net_init(): initialize network for multicast * returns: structure with network related information */ net_info_t *net_init(const char *mnet) { struct ip_mreq mreq; const int ttl = 64; /* TTL of 64 should be enough */ u_char loop = 0; net_info_t *net_info = NULL; net_info = (net_info_t *) malloc(sizeof(net_info_t)); if (!net_info) return NULL; memset(net_info, 0, sizeof(net_info_t)); /* network setup */ net_info->server.sin_family = AF_INET; net_info->server.sin_port = htons(DNBD_PORT); net_info->sock = socket(PF_INET, SOCK_DGRAM, 0); if (!inet_aton(mnet, &net_info->server.sin_addr)) { fprintf(stderr, "ERROR: multicast group %s is not a valid address!\n", mnet); goto out_free; } if (bind (net_info->sock, (struct sockaddr *) &net_info->server, sizeof(net_info->server)) < 0) { fprintf(stderr, "ERROR: binding socket!\n"); goto out_free; } if (!inet_aton(mnet, &net_info->groupnet.sin_addr)) { fprintf(stderr, "ERROR: multicast group %s is not a valid address!\n", mnet); goto out_free; } /* multicast setup */ net_info->groupnet.sin_family = AF_INET; net_info->groupnet.sin_port = htons(DNBD_PORT); mreq.imr_interface.s_addr = htonl(INADDR_ANY); memcpy(&mreq.imr_multiaddr, &net_info->groupnet.sin_addr, sizeof(struct in_addr)); if (setsockopt (net_info->sock, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) { fprintf(stderr, "ERROR: cannot add multicast membership!\n"); goto out_free; } if (setsockopt(net_info->sock, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0) { fprintf(stderr, "ERROR: Setting TTL to 2\n"); goto out_free; } /* no looping, please */ if (setsockopt (net_info->sock, IPPROTO_IP, IP_MULTICAST_LOOP, &loop, sizeof(loop)) < 0) { fprintf(stderr, "ERROR: cannot disable multicast looping!\n"); goto out_free; } goto out; out_free: fprintf(stderr, "hint: check kernel multicast support, multicast routing\n"); if (net_info) free(net_info); net_info = NULL; out: return net_info; }