File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / quagga / babeld / net.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue Oct 9 09:22:28 2012 UTC (11 years, 9 months ago) by misho
Branches: quagga, MAIN
CVS tags: v0_99_22p0, v0_99_22, v0_99_21, HEAD
quagga

    1: /*  
    2:  *  This file is free software: you may copy, redistribute and/or modify it  
    3:  *  under the terms of the GNU General Public License as published by the  
    4:  *  Free Software Foundation, either version 2 of the License, or (at your  
    5:  *  option) any later version.  
    6:  *  
    7:  *  This file is distributed in the hope that it will be useful, but  
    8:  *  WITHOUT ANY WARRANTY; without even the implied warranty of  
    9:  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU  
   10:  *  General Public License for more details.  
   11:  *  
   12:  *  You should have received a copy of the GNU General Public License  
   13:  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.  
   14:  *  
   15:  * This file incorporates work covered by the following copyright and  
   16:  * permission notice:  
   17:  *  
   18: Copyright (c) 2007, 2008 by Juliusz Chroboczek
   19: 
   20: Permission is hereby granted, free of charge, to any person obtaining a copy
   21: of this software and associated documentation files (the "Software"), to deal
   22: in the Software without restriction, including without limitation the rights
   23: to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
   24: copies of the Software, and to permit persons to whom the Software is
   25: furnished to do so, subject to the following conditions:
   26: 
   27: The above copyright notice and this permission notice shall be included in
   28: all copies or substantial portions of the Software.
   29: 
   30: THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
   31: IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
   32: FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
   33: AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
   34: LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
   35: OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
   36: THE SOFTWARE.
   37: */
   38: 
   39: #include <unistd.h>
   40: #include <fcntl.h>
   41: #include <string.h>
   42: #include <sys/ioctl.h>
   43: #include <sys/types.h>
   44: #include <sys/uio.h>
   45: #include <sys/socket.h>
   46: #include <netinet/in.h>
   47: #include <arpa/inet.h>
   48: #include <errno.h>
   49: 
   50: #include "babeld.h"
   51: #include "util.h"
   52: #include "net.h"
   53: 
   54: int
   55: babel_socket(int port)
   56: {
   57:     struct sockaddr_in6 sin6;
   58:     int s, rc;
   59:     int saved_errno;
   60:     int one = 1, zero = 0;
   61:     const int ds = 0xc0;        /* CS6 - Network Control */
   62: 
   63:     s = socket(PF_INET6, SOCK_DGRAM, 0);
   64:     if(s < 0)
   65:         return -1;
   66: 
   67:     rc = setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, &one, sizeof(one));
   68:     if(rc < 0)
   69:         goto fail;
   70: 
   71:     rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
   72:     if(rc < 0)
   73:         goto fail;
   74: 
   75:     rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
   76:                     &zero, sizeof(zero));
   77:     if(rc < 0)
   78:         goto fail;
   79: 
   80:     rc = setsockopt(s, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
   81:                     &one, sizeof(one));
   82:     if(rc < 0)
   83:         goto fail;
   84: 
   85:     rc = setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
   86:                     &one, sizeof(one));
   87:     if(rc < 0)
   88:         goto fail;
   89: 
   90: #ifdef IPV6_TCLASS
   91:     rc = setsockopt(s, IPPROTO_IPV6, IPV6_TCLASS, &ds, sizeof(ds));
   92: #else
   93:     rc = -1;
   94:     errno = ENOSYS;
   95: #endif
   96:     if(rc < 0)
   97:         perror("Couldn't set traffic class");
   98: 
   99:     rc = fcntl(s, F_GETFL, 0);
  100:     if(rc < 0)
  101:         goto fail;
  102: 
  103:     rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
  104:     if(rc < 0)
  105:         goto fail;
  106: 
  107:     rc = fcntl(s, F_GETFD, 0);
  108:     if(rc < 0)
  109:         goto fail;
  110: 
  111:     rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
  112:     if(rc < 0)
  113:         goto fail;
  114: 
  115:     memset(&sin6, 0, sizeof(sin6));
  116:     sin6.sin6_family = AF_INET6;
  117:     sin6.sin6_port = htons(port);
  118:     rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
  119:     if(rc < 0)
  120:         goto fail;
  121: 
  122:     return s;
  123: 
  124:  fail:
  125:     saved_errno = errno;
  126:     close(s);
  127:     errno = saved_errno;
  128:     return -1;
  129: }
  130: 
  131: int
  132: babel_recv(int s, void *buf, int buflen, struct sockaddr *sin, int slen)
  133: {
  134:     struct iovec iovec;
  135:     struct msghdr msg;
  136:     int rc;
  137: 
  138:     memset(&msg, 0, sizeof(msg));
  139:     iovec.iov_base = buf;
  140:     iovec.iov_len = buflen;
  141:     msg.msg_name = sin;
  142:     msg.msg_namelen = slen;
  143:     msg.msg_iov = &iovec;
  144:     msg.msg_iovlen = 1;
  145: 
  146:     rc = recvmsg(s, &msg, 0);
  147:     return rc;
  148: }
  149: 
  150: int
  151: babel_send(int s,
  152:            void *buf1, int buflen1, void *buf2, int buflen2,
  153:            struct sockaddr *sin, int slen)
  154: {
  155:     struct iovec iovec[2];
  156:     struct msghdr msg;
  157:     int rc;
  158: 
  159:     iovec[0].iov_base = buf1;
  160:     iovec[0].iov_len = buflen1;
  161:     iovec[1].iov_base = buf2;
  162:     iovec[1].iov_len = buflen2;
  163:     memset(&msg, 0, sizeof(msg));
  164:     msg.msg_name = (struct sockaddr*)sin;
  165:     msg.msg_namelen = slen;
  166:     msg.msg_iov = iovec;
  167:     msg.msg_iovlen = 2;
  168: 
  169:  again:
  170:     rc = sendmsg(s, &msg, 0);
  171:     if(rc < 0) {
  172:         if(errno == EINTR)
  173:             goto again;
  174:         else if(errno == EAGAIN) {
  175:             int rc2;
  176:             rc2 = wait_for_fd(1, s, 5);
  177:             if(rc2 > 0)
  178:                 goto again;
  179:             errno = EAGAIN;
  180:         }
  181:     }
  182:     return rc;
  183: }
  184: 
  185: int
  186: tcp_server_socket(int port, int local)
  187: {
  188:     struct sockaddr_in6 sin6;
  189:     int s, rc, saved_errno;
  190:     int one = 1;
  191: 
  192:     s = socket(PF_INET6, SOCK_STREAM, 0);
  193:     if(s < 0)
  194:         return -1;
  195: 
  196:     rc = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
  197:     if(rc < 0)
  198:         goto fail;
  199: 
  200:     rc = fcntl(s, F_GETFL, 0);
  201:     if(rc < 0)
  202:         goto fail;
  203: 
  204:     rc = fcntl(s, F_SETFL, (rc | O_NONBLOCK));
  205:     if(rc < 0)
  206:         goto fail;
  207: 
  208:     rc = fcntl(s, F_GETFD, 0);
  209:     if(rc < 0)
  210:         goto fail;
  211: 
  212:     rc = fcntl(s, F_SETFD, rc | FD_CLOEXEC);
  213:     if(rc < 0)
  214:         goto fail;
  215: 
  216:     memset(&sin6, 0, sizeof(sin6));
  217:     sin6.sin6_family = AF_INET6;
  218:     sin6.sin6_port = htons(port);
  219:     if(local) {
  220:         rc = inet_pton(AF_INET6, "::1", &sin6.sin6_addr);
  221:         if(rc < 0)
  222:             goto fail;
  223:     }
  224:     rc = bind(s, (struct sockaddr*)&sin6, sizeof(sin6));
  225:     if(rc < 0)
  226:         goto fail;
  227: 
  228:     rc = listen(s, 2);
  229:     if(rc < 0)
  230:         goto fail;
  231: 
  232:     return s;
  233: 
  234:  fail:
  235:     saved_errno = errno;
  236:     close(s);
  237:     errno = saved_errno;
  238:     return -1;
  239: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>