~ubuntu-branches/ubuntu/trusty/netpipe/trusty

« back to all changes in this revision

Viewing changes to src/sctp6.c

  • Committer: Bazaar Package Importer
  • Author(s): Camm Maguire
  • Date: 2010-01-06 19:07:32 UTC
  • mfrom: (4.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20100106190732-fg9urgk31weolrcs
Tags: 3.7.1-1
* New upstream release
* Bug fix: "debian/watch fails to report upstream's version", thanks
  to Raphael Geissert (Closes: #450010).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*****************************************************************************/
 
2
/* "NetPIPE" -- Network Protocol Independent Performance Evaluator.          */
 
3
/* Copyright 1997, 1998 Iowa State University Research Foundation, Inc.      */
 
4
/*                                                                           */
 
5
/* This program is free software; you can redistribute it and/or modify      */
 
6
/* it under the terms of the GNU General Public License as published by      */
 
7
/* the Free Software Foundation.  You should have received a copy of the     */
 
8
/* GNU General Public License along with this program; if not, write to the  */
 
9
/* Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.   */
 
10
/*                                                                           */
 
11
/*     * sctp6.c             ---- SCTP over IPv6 calls source                */
 
12
/*****************************************************************************/
 
13
#include    "netpipe.h"
 
14
 
 
15
#if defined (MPLITE)
 
16
#include "mplite.h"
 
17
#endif
 
18
 
 
19
 
 
20
int doing_reset = 0;
 
21
 
 
22
void Init(ArgStruct *p, int* pargc, char*** pargv)
 
23
{
 
24
    p->reset_conn = 0; /* Default to not resetting connection */
 
25
    p->prot.sndbufsz = p->prot.rcvbufsz = 0;
 
26
    p->tr = 0;     /* The transmitter will be set using the -h host flag. */
 
27
    p->rcv = 1;
 
28
}
 
29
 
 
30
void Setup(ArgStruct *p)
 
31
{
 
32
    
 
33
    int one = 1;
 
34
    int sockfd;
 
35
    struct sockaddr_in6 *lsin1, *lsin2; /* ptr to sockaddr_in6 in ArgStruct */
 
36
    char *host;
 
37
    struct hostent *hp;
 
38
    struct protoent *proto;
 
39
    int send_size, recv_size, sizeofint = sizeof(int);
 
40
    
 
41
    
 
42
    host = p->host;                           /* copy ptr to hostname */ 
 
43
    
 
44
    lsin1 = &(p->prot.sin1);
 
45
    lsin2 = &(p->prot.sin2);
 
46
    
 
47
    bzero((char *) lsin1, sizeof(*lsin1));
 
48
    bzero((char *) lsin2, sizeof(*lsin2));
 
49
    
 
50
    if ( (sockfd = socket(AF_INET6, SOCK_STREAM, IPPROTO_SCTP)) < 0){
 
51
        printf("NetPIPE: can't open stream socket! errno=%d\n", errno);
 
52
        exit(-4);
 
53
    }
 
54
    
 
55
    if(!(proto = getprotobyname("sctp"))){
 
56
        printf("NetPIPE: protocol 'sctp' unknown!\n");
 
57
        exit(555);
 
58
    }
 
59
    
 
60
    /* Attempt to set SCTP_NODELAY */
 
61
 
 
62
    if(setsockopt(sockfd, proto->p_proto, SCTP_NODELAY, &one, sizeof(one)) < 0)
 
63
    {
 
64
        printf("NetPIPE: setsockopt: SCTP_NODELAY failed! errno=%d\n", errno);
 
65
        exit(556);
 
66
    }
 
67
    
 
68
    /* If requested, set the send and receive buffer sizes */
 
69
    
 
70
    if(p->prot.sndbufsz > 0)
 
71
    {
 
72
        if(setsockopt(sockfd, SOL_SOCKET, SO_SNDBUF, &(p->prot.sndbufsz), 
 
73
                      sizeof(p->prot.sndbufsz)) < 0)
 
74
        {
 
75
            printf("NetPIPE: setsockopt: SO_SNDBUF failed! errno=%d\n", errno);
 
76
            printf("You may have asked for a buffer larger than the system");
 
77
            printf("can handle\n");
 
78
 
 
79
            exit(556);
 
80
        }
 
81
        if(setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &(p->prot.rcvbufsz), 
 
82
                      sizeof(p->prot.rcvbufsz)) < 0)
 
83
        {
 
84
            printf("NetPIPE: setsockopt: SO_RCVBUF failed! errno=%d\n", errno);
 
85
            printf("You may have asked for a buffer larger than the system");
 
86
            printf("can handle\n");
 
87
            exit(556);
 
88
        }
 
89
    }
 
90
    getsockopt(sockfd, SOL_SOCKET, SO_SNDBUF,
 
91
               (char *) &send_size, (void *) &sizeofint);
 
92
    getsockopt(sockfd, SOL_SOCKET, SO_RCVBUF,
 
93
               (char *) &recv_size, (void *) &sizeofint);
 
94
    
 
95
    if(!doing_reset) {
 
96
        fprintf(stderr,"Send and receive buffers are %d and %d bytes\n",
 
97
                send_size, recv_size);
 
98
        fprintf(stderr,
 
99
                "(A bug in Linux doubles the requested buffer sizes)\n");
 
100
    }
 
101
    
 
102
    if( p->tr ) {                             /* Primary transmitter */
 
103
        
 
104
        lsin1->sin6_family = AF_INET6;
 
105
        
 
106
        /* First attempt to convert the string to an IPv6 */
 
107
        /* address. */
 
108
        /* If the user supplied a real host name this will fail and */
 
109
        /* we'll then do a name lookup. */
 
110
        
 
111
        if (inet_pton(AF_INET6, host, &lsin1->sin6_addr) == 0)
 
112
        {
 
113
            if ((hp = gethostbyname2(host, AF_INET6)) == NULL)
 
114
            {
 
115
                printf("NetPIPE: invalid hostname '%s'\n", host);
 
116
                exit(-5);
 
117
            }
 
118
            
 
119
            if (hp->h_addrtype != AF_INET6) 
 
120
            {
 
121
                printf("NetPIPE: invalid hostname '%s'\n", host);
 
122
                exit(-5);
 
123
            }
 
124
            bcopy(hp->h_addr, (char*) &(lsin1->sin6_addr), 
 
125
                  hp->h_length);
 
126
        }
 
127
         
 
128
        lsin1->sin6_port = htons(p->port);
 
129
        
 
130
        p->commfd = sockfd;
 
131
        
 
132
    } else if( p->rcv ) {                     /* we are the receiver */
 
133
        
 
134
        bzero((char *) lsin1, sizeof(*lsin1));
 
135
        lsin1->sin6_family      = AF_INET6;
 
136
        lsin1->sin6_len         = sizeof(*lsin1);
 
137
        lsin1->sin6_port        = htons(p->port);
 
138
        /* Setting this to all 0 is the "ANY" address. */
 
139
        bzero(&lsin1->sin6_addr, sizeof(lsin1->sin6_addr));
 
140
        
 
141
        if (bind(sockfd, (struct sockaddr *) lsin1, sizeof(*lsin1)) < 0){
 
142
            printf("NetPIPE: server: bind on local address failed! errno=%d", 
 
143
                   errno);
 
144
            exit(-6);
 
145
        }
 
146
        
 
147
        p->servicefd = sockfd;
 
148
    }
 
149
    p->upper = send_size + recv_size;
 
150
    
 
151
    establish(p);                               /* Establish connections */
 
152
    
 
153
}   
 
154
 
 
155
static int
 
156
readFully(int fd, void *obuf, int len)
 
157
{
 
158
    int bytesLeft = len;
 
159
    char *buf = (char *) obuf;
 
160
    int bytesRead = 0;
 
161
 
 
162
    while (bytesLeft > 0 &&
 
163
           (bytesRead = read(fd, (void *) buf, bytesLeft)) > 0)
 
164
    {
 
165
        bytesLeft -= bytesRead;
 
166
        buf += bytesRead;
 
167
    }
 
168
    if (bytesRead <= 0) return bytesRead;
 
169
    return len;
 
170
}
 
171
 
 
172
void Sync(ArgStruct *p)
 
173
{
 
174
    char s[] = "SyncMe", response[] = "      ";
 
175
 
 
176
    if (write(p->commfd, s, strlen(s)) < 0 ||           /* Write to nbor */
 
177
        readFully(p->commfd, response, strlen(s)) < 0)  /* Read from nbor */
 
178
    {
 
179
        perror("NetPIPE: error writing or reading synchronization string");
 
180
        exit(3);
 
181
    }
 
182
    if (strncmp(s, response, strlen(s)))
 
183
    {
 
184
        fprintf(stderr, "NetPIPE: Synchronization string incorrect! |%s|\n", 
 
185
                response);
 
186
        exit(3);
 
187
    }
 
188
}
 
189
 
 
190
void PrepareToReceive(ArgStruct *p)
 
191
{
 
192
    /*
 
193
      The Berkeley sockets interface doesn't have a method to pre-post
 
194
      a buffer for reception of data.
 
195
    */
 
196
}
 
197
 
 
198
void SendData(ArgStruct *p)
 
199
{
 
200
    int bytesWritten, bytesLeft;
 
201
    char *q;
 
202
 
 
203
    bytesLeft = p->bufflen;
 
204
    bytesWritten = 0;
 
205
    q = p->s_ptr;
 
206
    while (bytesLeft > 0 &&
 
207
           (bytesWritten = write(p->commfd, q, bytesLeft)) > 0)
 
208
    {
 
209
        bytesLeft -= bytesWritten;
 
210
        q += bytesWritten;
 
211
    }
 
212
    if (bytesWritten == -1)
 
213
    {
 
214
        printf("NetPIPE: write: error encountered, errno=%d\n", errno);
 
215
        exit(401);
 
216
    }
 
217
}
 
218
 
 
219
void RecvData(ArgStruct *p)
 
220
{
 
221
    int bytesLeft;
 
222
    int bytesRead;
 
223
    char *q;
 
224
 
 
225
    bytesLeft = p->bufflen;
 
226
    bytesRead = 0;
 
227
    q = p->r_ptr;
 
228
    while (bytesLeft > 0 &&
 
229
           (bytesRead = read(p->commfd, q, bytesLeft)) > 0)
 
230
    {
 
231
        bytesLeft -= bytesRead;
 
232
        q += bytesRead;
 
233
    }
 
234
    if (bytesLeft > 0 && bytesRead == 0)
 
235
    {
 
236
        printf("NetPIPE: \"end of file\" encountered reading from socket\n");
 
237
    }
 
238
    else if (bytesRead == -1)
 
239
    {
 
240
        printf("NetPIPE: read: error encountered, errno=%d\n", errno);
 
241
        exit(401);
 
242
    }
 
243
}
 
244
 
 
245
/* uint32_t is used to insure that the integer size is the same even in tests 
 
246
 * between 64-bit and 32-bit architectures. */
 
247
 
 
248
void SendTime(ArgStruct *p, double *t)
 
249
{
 
250
    uint32_t ltime, ntime;
 
251
 
 
252
    /*
 
253
      Multiply the number of seconds by 1e8 to get time in 0.01 microseconds
 
254
      and convert value to an unsigned 32-bit integer.
 
255
    */
 
256
    ltime = (uint32_t)(*t * 1.e8);
 
257
 
 
258
    /* Send time in network order */
 
259
    ntime = htonl(ltime);
 
260
    if (write(p->commfd, (char *)&ntime, sizeof(uint32_t)) < 0)
 
261
    {
 
262
        printf("NetPIPE: write failed in SendTime: errno=%d\n", errno);
 
263
        exit(301);
 
264
    }
 
265
}
 
266
 
 
267
void RecvTime(ArgStruct *p, double *t)
 
268
{
 
269
    uint32_t ltime, ntime;
 
270
    int bytesRead;
 
271
 
 
272
    bytesRead = readFully(p->commfd, (void *)&ntime, sizeof(uint32_t));
 
273
    if (bytesRead < 0)
 
274
    {
 
275
        printf("NetPIPE: read failed in RecvTime: errno=%d\n", errno);
 
276
        exit(302);
 
277
    }
 
278
    else if (bytesRead != sizeof(uint32_t))
 
279
    {
 
280
        fprintf(stderr, "NetPIPE: partial read in RecvTime of %d bytes\n",
 
281
                bytesRead);
 
282
        exit(303);
 
283
    }
 
284
    ltime = ntohl(ntime);
 
285
 
 
286
    /* Result is ltime (in microseconds) divided by 1.0e8 to get seconds */
 
287
 
 
288
    *t = (double)ltime / 1.0e8;
 
289
}
 
290
 
 
291
void SendRepeat(ArgStruct *p, int rpt)
 
292
{
 
293
    uint32_t lrpt, nrpt;
 
294
 
 
295
    lrpt = rpt;
 
296
    /* Send repeat count as a long in network order */
 
297
    nrpt = htonl(lrpt);
 
298
    if (write(p->commfd, (void *) &nrpt, sizeof(uint32_t)) < 0)
 
299
    {
 
300
        printf("NetPIPE: write failed in SendRepeat: errno=%d\n", errno);
 
301
        exit(304);
 
302
    }
 
303
}
 
304
 
 
305
void RecvRepeat(ArgStruct *p, int *rpt)
 
306
{
 
307
    uint32_t lrpt, nrpt;
 
308
    int bytesRead;
 
309
 
 
310
    bytesRead = readFully(p->commfd, (void *)&nrpt, sizeof(uint32_t));
 
311
    if (bytesRead < 0)
 
312
    {
 
313
        printf("NetPIPE: read failed in RecvRepeat: errno=%d\n", errno);
 
314
        exit(305);
 
315
    }
 
316
    else if (bytesRead != sizeof(uint32_t))
 
317
    {
 
318
        fprintf(stderr, "NetPIPE: partial read in RecvRepeat of %d bytes\n",
 
319
                bytesRead);
 
320
        exit(306);
 
321
    }
 
322
    lrpt = ntohl(nrpt);
 
323
 
 
324
    *rpt = lrpt;
 
325
}
 
326
 
 
327
void establish(ArgStruct *p)
 
328
{
 
329
    int one = 1;
 
330
    socklen_t clen;
 
331
    struct protoent *proto;
 
332
 
 
333
    clen = (socklen_t) sizeof(p->prot.sin2);
 
334
 
 
335
    if( p->tr ){
 
336
 
 
337
        while( connect(p->commfd, (struct sockaddr *) &(p->prot.sin1),
 
338
                       sizeof(p->prot.sin1)) < 0 ) {
 
339
 
 
340
            /* If we are doing a reset and we get a connection refused from
 
341
             * the connect() call, assume that the other node has not yet
 
342
             * gotten to its corresponding accept() call and keep trying until
 
343
             * we have success.
 
344
             */
 
345
            if(!doing_reset || errno != ECONNREFUSED) {
 
346
                printf("Client: Cannot Connect! errno=%d\n",errno);
 
347
                exit(-10);
 
348
            } 
 
349
        
 
350
        }
 
351
 
 
352
    } else if( p->rcv ) {
 
353
 
 
354
        /* SERVER */
 
355
        listen(p->servicefd, 5);
 
356
        p->commfd = accept(p->servicefd, (struct sockaddr *) &(p->prot.sin2), 
 
357
                           &clen);
 
358
 
 
359
        if(p->commfd < 0){
 
360
            printf("Server: Accept Failed! errno=%d\n",errno);
 
361
            exit(-12);
 
362
        }
 
363
 
 
364
        /*
 
365
         * Attempt to set SCTP_NODELAY. SCTP_NODELAY may or may not be 
 
366
         * propagated to accepted sockets.
 
367
         */
 
368
        if(!(proto = getprotobyname("sctp"))){
 
369
            printf("unknown protocol!\n");
 
370
            exit(555);
 
371
        }
 
372
 
 
373
        if(setsockopt(p->commfd, proto->p_proto, SCTP_NODELAY,
 
374
                      &one, sizeof(one)) < 0)
 
375
        {
 
376
            printf("setsockopt: SCTP_NODELAY failed! errno=%d\n", errno);
 
377
            exit(556);
 
378
        }
 
379
 
 
380
        /* If requested, set the send and receive buffer sizes */
 
381
        if(p->prot.sndbufsz > 0)
 
382
        {
 
383
            if(setsockopt(p->commfd, SOL_SOCKET, SO_SNDBUF, 
 
384
                          &(p->prot.sndbufsz), 
 
385
                          sizeof(p->prot.sndbufsz)) < 0)
 
386
            {
 
387
                printf("setsockopt: SO_SNDBUF failed! errno=%d\n", errno);
 
388
                exit(556);
 
389
            }
 
390
            if(setsockopt(p->commfd, SOL_SOCKET, SO_RCVBUF, 
 
391
                          &(p->prot.rcvbufsz), 
 
392
                          sizeof(p->prot.rcvbufsz)) < 0)
 
393
            {
 
394
                printf("setsockopt: SO_RCVBUF failed! errno=%d\n", errno);
 
395
                exit(556);
 
396
            }
 
397
        }
 
398
    }
 
399
}
 
400
 
 
401
void CleanUp(ArgStruct *p)
 
402
{
 
403
    char *quit="QUIT";
 
404
 
 
405
    if (p->tr) {
 
406
 
 
407
        write(p->commfd,quit, 5);
 
408
        read(p->commfd, quit, 5);
 
409
        close(p->commfd);
 
410
 
 
411
    } else if( p->rcv ) {
 
412
 
 
413
        read(p->commfd,quit, 5);
 
414
        write(p->commfd,quit,5);
 
415
        close(p->commfd);
 
416
        close(p->servicefd);
 
417
 
 
418
    }
 
419
}
 
420
 
 
421
 
 
422
void Reset(ArgStruct *p)
 
423
{
 
424
  
 
425
    /* Reset sockets */
 
426
 
 
427
    if(p->reset_conn) {
 
428
 
 
429
        doing_reset = 1;
 
430
 
 
431
        /* Close the sockets */
 
432
 
 
433
        CleanUp(p);
 
434
 
 
435
        /* Now open and connect new sockets */
 
436
 
 
437
        Setup(p);
 
438
 
 
439
    }
 
440
 
 
441
}
 
442
 
 
443
void AfterAlignmentInit(ArgStruct *p)
 
444
{
 
445
 
 
446
}
 
447