~ubuntu-branches/ubuntu/precise/nfs-utils/precise-proposed

« back to all changes in this revision

Viewing changes to support/nfs/svc_socket.c

  • Committer: Bazaar Package Importer
  • Author(s): Nathaniel McCallum
  • Date: 2004-09-10 13:10:39 UTC
  • Revision ID: james.westby@ubuntu.com-20040910131039-qxfjx4pwgoz6imbv
Tags: upstream-1.0.6
ImportĀ upstreamĀ versionĀ 1.0.6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2002 Free Software Foundation, Inc.
 
2
   This file is part of the GNU C Library.
 
3
 
 
4
   The GNU C Library is free software; you can redistribute it and/or
 
5
   modify it under the terms of the GNU Lesser General Public
 
6
   License as published by the Free Software Foundation; either
 
7
   version 2.1 of the License, or (at your option) any later version.
 
8
 
 
9
   The GNU C Library is distributed in the hope that it will be useful,
 
10
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
11
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
12
   Lesser General Public License for more details.
 
13
 
 
14
   You should have received a copy of the GNU Lesser General Public
 
15
   License along with the GNU C Library; if not, write to the Free
 
16
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
 
17
   02111-1307 USA.  */
 
18
 
 
19
#include <stdio.h>
 
20
#include <string.h>
 
21
#include <unistd.h>
 
22
#include <netdb.h>
 
23
#include <rpc/rpc.h>
 
24
#include <sys/socket.h>
 
25
#include <errno.h>
 
26
 
 
27
#ifdef _LIBC
 
28
# include <libintl.h>
 
29
#else
 
30
# ifndef _
 
31
#  define _(s)                  (s)
 
32
# endif
 
33
# define __socket(d, t, p)      socket ((d), (t), (p))
 
34
# define __close(f)             close ((f))
 
35
#endif
 
36
 
 
37
static int
 
38
svc_socket (u_long number, int type, int protocol, int reuse)
 
39
{
 
40
  struct sockaddr_in addr;
 
41
  socklen_t len = sizeof (struct sockaddr_in);
 
42
  char rpcdata [1024], servdata [1024];
 
43
  struct rpcent rpcbuf, *rpcp;
 
44
  struct servent servbuf, *servp;
 
45
  int sock, ret;
 
46
  const char *proto = protocol == IPPROTO_TCP ? "tcp" : "udp";
 
47
 
 
48
  if ((sock = __socket (AF_INET, type, protocol)) < 0)
 
49
    {
 
50
      perror (_("svc_socket: socket creation problem"));
 
51
      return sock;
 
52
    }
 
53
 
 
54
  if (reuse)
 
55
    {
 
56
      ret = 1;
 
57
      ret = setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &ret,
 
58
                        sizeof (ret));
 
59
      if (ret < 0)
 
60
        {
 
61
          perror (_("svc_socket: socket reuse problem"));
 
62
          return ret;
 
63
        }
 
64
    }
 
65
 
 
66
  __bzero ((char *) &addr, sizeof (addr));
 
67
  addr.sin_family = AF_INET;
 
68
 
 
69
  ret = getrpcbynumber_r (number, &rpcbuf, rpcdata, sizeof rpcdata,
 
70
                          &rpcp);
 
71
  if (ret == 0 && rpcp != NULL)
 
72
    {
 
73
      /* First try name.  */
 
74
      ret = getservbyname_r (rpcp->r_name, proto, &servbuf, servdata,
 
75
                             sizeof servdata, &servp);
 
76
      if ((ret != 0 || servp == NULL) && rpcp->r_aliases)
 
77
        {
 
78
          const char **a;
 
79
 
 
80
          /* Then we try aliases.  */
 
81
          for (a = (const char **) rpcp->r_aliases; *a != NULL; a++) 
 
82
            {
 
83
              ret = getservbyname_r (*a, proto, &servbuf, servdata,
 
84
                                     sizeof servdata, &servp);
 
85
              if (ret == 0 && servp != NULL)
 
86
                break;
 
87
            }
 
88
        }
 
89
    }
 
90
 
 
91
  if (ret == 0 && servp != NULL)
 
92
    {
 
93
      addr.sin_port = servp->s_port;
 
94
      if (bind (sock, (struct sockaddr *) &addr, len) < 0)
 
95
        {
 
96
          perror (_("svc_socket: bind problem"));
 
97
          (void) __close (sock);
 
98
          sock = -1;
 
99
        }
 
100
    }
 
101
  else
 
102
    {
 
103
      if (bindresvport (sock, &addr))
 
104
        {
 
105
          addr.sin_port = 0;
 
106
          if (bind (sock, (struct sockaddr *) &addr, len) < 0)
 
107
            {
 
108
              perror (_("svc_socket: bind problem"));
 
109
              (void) __close (sock);
 
110
              sock = -1;
 
111
            }
 
112
        }
 
113
    }
 
114
 
 
115
  return sock;
 
116
}
 
117
 
 
118
/*
 
119
 * Create and bind a TCP socket based on program number
 
120
 */
 
121
int
 
122
svctcp_socket (u_long number, int reuse)
 
123
{
 
124
  return svc_socket (number, SOCK_STREAM, IPPROTO_TCP, reuse);
 
125
}
 
126
 
 
127
/*
 
128
 * Create and bind a UDP socket based on program number
 
129
 */
 
130
int
 
131
svcudp_socket (u_long number, int reuse)
 
132
{
 
133
  return svc_socket (number, SOCK_DGRAM, IPPROTO_UDP, reuse);
 
134
}
 
135
 
 
136
#ifdef TEST
 
137
static int
 
138
check (u_long number, u_short port, int protocol, int reuse)
 
139
{
 
140
  int socket;
 
141
  int result;
 
142
  struct sockaddr_in addr;
 
143
  socklen_t len = sizeof (struct sockaddr_in);
 
144
 
 
145
  if (protocol == IPPROTO_TCP)
 
146
    socket = svctcp_socket (number, reuse);
 
147
  else
 
148
    socket = svcudp_socket (number, reuse);
 
149
 
 
150
  if (socket < 0)
 
151
    return 1;
 
152
 
 
153
  result = getsockname (socket, (struct sockaddr *) &addr, &len);
 
154
  if (result == 0)
 
155
    {
 
156
      if (port != 0 && ntohs (addr.sin_port) != port)
 
157
        printf ("Program: %ld, expect port: %d, got: %d\n",
 
158
                number, port, ntohs (addr.sin_port)); 
 
159
      else
 
160
        printf ("Program: %ld, port: %d\n",
 
161
                number, ntohs (addr.sin_port)); 
 
162
    }
 
163
 
 
164
  close (socket);
 
165
  return result;
 
166
}
 
167
 
 
168
int
 
169
main (void)
 
170
{
 
171
  int result = 0;
 
172
 
 
173
  result += check (100001, 0, IPPROTO_TCP, 0);
 
174
  result += check (100001, 0, IPPROTO_UDP, 0);
 
175
  result += check (100003, 2049, IPPROTO_TCP, 1);
 
176
  result += check (100003, 2049, IPPROTO_UDP, 1);
 
177
 
 
178
  return result;
 
179
}
 
180
#endif