modules/up/src/util/net.cc

/* [<][>]
[^][v][top][bottom][index][help] */

FUNCTIONS

This source file includes following functions.
  1. init_ipAddr
  2. setAddress
  3. setAddress
  4. Socket
  5. setsockopt
  6. write
  7. read
  8. wait_for_reply
  9. TCP
  10. init_server
  11. TCP
  12. TCP
  13. init_tcp
  14. UDP
  15. UDP

/*
//  $Id: net.cc,v 1.1.1.1 2000/03/10 16:32:15 engin Exp $
//
//  Copyright (c) 1994 by the University of Southern California
//  All rights reserved.
//
//  Permission to use, copy, modify, and distribute this software and its
//  documentation in source and binary forms for lawful non-commercial
//  purposes and without fee is hereby granted, provided that the above
//  copyright notice appear in all copies and that both the copyright
//  notice and this permission notice appear in supporting documentation,
//  and that any documentation, advertising materials, and other materials
//  related to such distribution and use acknowledge that the software was
//  developed by the University of Southern California, Information
//  Sciences Institute. The name of the USC may not be used to endorse or
//  promote products derived from this software without specific prior
//  written permission.
//
//  THE UNIVERSITY OF SOUTHERN CALIFORNIA DOES NOT MAKE ANY
//  REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR ANY
//  PURPOSE.  THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
//  IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
//  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE,
//  TITLE, AND NON-INFRINGEMENT.
//
//  IN NO EVENT SHALL USC, OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
//  SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES, WHETHER IN CONTRACT, TORT,
//  OR OTHER FORM OF ACTION, ARISING OUT OF OR IN CONNECTION WITH, THE USE
//  OR PERFORMANCE OF THIS SOFTWARE.
//
//  Questions concerning this software should be directed to
//  ratoolset@isi.edu.
//
//  Author(s): eddy@isi.edu
*/

#include "net.hh"

//
// setName sets either the hexaddr or the hostname, then calls
// _getHostent() to fill in the hostent and copy the official
// values into the redundant vars in the ipAddr class
//
void
ipAddr::init_ipAddr () {
/* [<][>][^][v][top][bottom][index][help] */
    bzero ((char *) &hostname, MAXHOSTNAMELEN);
    bzero ((char *) &dottedaddr, sizeof (dottedaddr));
    bzero ((char *) &maskedaddr, sizeof (maskedaddr));
    bzero ((char *) &asname, sizeof (asname));
    hp = (struct hostent *) NULL;
    mask   = 32;                // default to a host, unless changed
    hexaddr = 0;
}

int
ipAddr::setAddress (const char *addr)
/* [<][>][^][v][top][bottom][index][help] */
{
    hp = (struct hostent *) NULL;
    hexaddr = (u_long) inet_addr (addr);
    if (hexaddr != INADDR_NONE) {
        hp = gethostbyaddr ((char *) &hexaddr, sizeof (hexaddr), AF_INET);
    } else {
        hp = gethostbyname ((char *) addr);
    }   
    if (hp) {
        bcopy (hp->h_addr, (caddr_t) &hexaddr, (size_t) hp->h_length);
        strcpy (hostname, hp->h_name);
    }
    if (hp == NULL && hexaddr == INADDR_NONE) 
        error.fatal ("Could not resolve %s\0", addr);
    return (error());
}

int
ipAddr::setAddress (u_long hex)
/* [<][>][^][v][top][bottom][index][help] */
{
    hp = (struct hostent *) NULL;
    hexaddr = hex;
    hp = gethostbyaddr ((char *) &hexaddr, sizeof (hexaddr), AF_INET);
    if (hp) {
        bcopy (hp->h_addr, (caddr_t) &hexaddr, (size_t) hp->h_length);
        strcpy (hostname, hp->h_name);
    }
    // we should do a range check on hexaddr and throw an exception
    if (!hp)
        error.fatal ("Could not set ipaddr for 0x%x", hex);
    return (error());
}

////////////////////////////////////////////////////////////////////////
Socket::Socket (u_int f, u_int t, u_int p)
/* [<][>][^][v][top][bottom][index][help] */
{
    bzero ((char *) &sockdst, sizeof (sockdst));
    bzero ((char *) &socksrc, sizeof (socksrc));
    send_flags = 0;
    sockdst.sin_family = family = f;
    sockdst.sin_port = proto = p;
    socksrc.sin_family = family = f;
    socksrc.sin_port = proto = p;
    in = out = NULL;
    type   = t;
    sock = socket (family, type, proto);
    if (sock < 0) 
        error.fatal ("socket");
}

int
Socket::setsockopt (int level, int optname, char *data, int dlen)
/* [<][>][^][v][top][bottom][index][help] */
{
    int on = 1;
    switch (level) {
      case SOL_SOCKET :
        if (optname & SO_DEBUG) {
            (void) ::setsockopt (sock, level, SO_DEBUG,
                                 (char *) &on, sizeof (on));
        }
        if (optname & SO_DONTROUTE) {
            (void) ::setsockopt (sock, level, SO_DONTROUTE,
                                 (char *) &on, sizeof (on));
        }
        if (optname & SO_SNDBUF) {
            error = ::setsockopt(sock, level, SO_SNDBUF,
                                 (char *)&data, dlen);
            if (error())
                return error.fatal ("setsocketopt: SO_SNDBUF");
        }
        break;                  // SOL_SOCKET
      case IPPROTO_IP:
        switch (optname) {
#ifdef IP_HDRINCL
         case IP_HDRINCL:
            error = ::setsockopt (sock, level, optname, (char *)&on, sizeof(on));
            if (error())
                error("setsockopt: IP_HDRINCL");
            return error();
            break;              // IP_HDRINCL
#endif IP_HDRINCL
        }
#ifdef IP_OPTIONS
      default:
        int err = ::setsockopt (sock, level, optname, (char *) data, dlen);
        if (err)
            error.fatal ("setsockopt: level: %d, optname: %d\n", level, optname);
        return error();
        break;
#endif IP_OPTIONS
    }
}

                    
int
Socket::write (char *buf, int len)
/* [<][>][^][v][top][bottom][index][help] */
{
    char *b = (char *) buf;
    int l = len;
    while (l > 0) {
        int c = ::write (sock, b, l);
        if (c < 0) {
            // Added by wlee@isi.edu
            if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
              errno = 0;
              continue;
            }
            return error.fatal ("write");
        }
        l -= c;
        b += c;
    }
    return (len - l);
}

int
Socket::read (char *buf, int len)
/* [<][>][^][v][top][bottom][index][help] */
{
    int c = -1;
    while (c < 0) {
        c = ::read (sock, buf, len);
        if (c < 0) {
            // Modified by wlee@isi.edu
            if (errno == EINTR || errno == EWOULDBLOCK || errno == EAGAIN) {
                errno = 0;
                continue;
            }
            return error.fatal ("Socket::read");
        }
    }
    return c;
}

int 
Socket::wait_for_reply (char *buffer, int size = MAXPACKETLEN, int seconds = 0)
/* [<][>][^][v][top][bottom][index][help] */
{
    fd_set fds;
    FD_ZERO (&fds);
    FD_SET  (sock, &fds);
    Timer timeout(seconds);
    int c = select (sock+1, &fds, (fd_set *) NULL, (fd_set *) NULL, timeout.tval());
    if (c > 0) {
        c = recvfrom ((char *)buffer, 1024);
    }
    if (c < 0) 
        error.fatal ("Socket.wait_for_reply");
    return c;                   // < 0 = count; 0 = timeout; > 0 = system err
}


////////////////////////////////////////////////////////////////////////
//
// open up a connection to listen on
//
////////////////////////////////////////////////////////////////////////
TCP::TCP (int p) :
/* [<][>][^][v][top][bottom][index][help] */
    Socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)
{
    init_server (p);
}

int TCP::init_server (int p) {
/* [<][>][^][v][top][bottom][index][help] */
    setLocalPort (p);
    bind();
    listen();
    if (error())
        error.fatal ("TCP socket");
}

TCP::TCP (char *hostname, int p) : Socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)
/* [<][>][^][v][top][bottom][index][help] */
{
    service = (struct servent *) NULL;
    init_tcp (hostname, p);
}

TCP::TCP (char *hostname, char *s) : Socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)
/* [<][>][^][v][top][bottom][index][help] */
{
    service = getservbyname (s, "tcp");
    if (service == NULL) {
        error.fatal ("tcp: unknown service: %s\n", s);
        return;
    }
    init_tcp (hostname, service->s_port);
}

int
TCP::init_tcp (char *hostname, int p)
/* [<][>][^][v][top][bottom][index][help] */
{
    ipaddr->setAddress (hostname);
    set_dstInaddr (ipaddr->getInaddr());
    setPort (p);
    port = p;
    connect ();
    return error();
}



////////////////////////////////////////////////////////////////////////
UDP::UDP (char *hostname, int p) : Socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)
/* [<][>][^][v][top][bottom][index][help] */
{
    init_udp (hostname, p);
}

UDP::UDP (char *hostname, char *s) : Socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)
/* [<][>][^][v][top][bottom][index][help] */
{
    service = getservbyname (s, "udp");
    if (service == NULL) {
        error.fatal ("udp: unknown service: %s\n", s);
        return;
    }
    init_udp (hostname, service->s_port);
}

/* [<][>][^][v][top][bottom][index][help] */