1/* 2 * $Id: atp_sreq.c,v 1.5 2002-01-17 06:08:55 srittau Exp $ 3 * 4 * Copyright (c) 1990,1991 Regents of The University of Michigan. 5 * All Rights Reserved. 6 * 7 * Permission to use, copy, modify, and distribute this software and 8 * its documentation for any purpose and without fee is hereby granted, 9 * provided that the above copyright notice appears in all copies and 10 * that both that copyright notice and this permission notice appear 11 * in supporting documentation, and that the name of The University 12 * of Michigan not be used in advertising or publicity pertaining to 13 * distribution of the software without specific, written prior 14 * permission. This software is supplied as is without expressed or 15 * implied warranties of any kind. 16 * 17 * Research Systems Unix Group 18 * The University of Michigan 19 * c/o Mike Clark 20 * 535 W. William Street 21 * Ann Arbor, Michigan 22 * +1-313-763-0525 23 * netatalk@itd.umich.edu 24 */ 25 26#ifdef HAVE_CONFIG_H 27#include "config.h" 28#endif /* HAVE_CONFIG_H */ 29 30#include <stdlib.h> 31#include <string.h> 32#include <sys/types.h> 33#include <sys/time.h> 34#include <errno.h> 35#include <sys/uio.h> 36#include <signal.h> 37 38#include <netinet/in.h> 39#include <netatalk/at.h> 40#include <netatalk/endian.h> 41 42#include <atalk/netddp.h> 43#include <atalk/atp.h> 44#include <atalk/util.h> 45 46#include "atp_internals.h" 47 48/* 49 * ah: open atp handle 50 * atpb: parameter block 51 * respcount: buffers available for response 52 * flags: ATP_XO, ATP_TREL 53 */ 54int 55atp_sreq( ATP ah, struct atp_block *atpb, int respcount, u_int8_t flags ) 56{ 57 struct atpbuf *req_buf; 58 int i; 59 60#ifdef EBUG 61 atp_print_bufuse( ah, "atp_sreq" ); 62#endif /* EBUG */ 63 64 /* check parameters 65 */ 66 if ( atpb->atp_sreqdlen < 4 || atpb->atp_sreqdlen > ATP_MAXDATA 67 || ( respcount < 0 ) || ( respcount > 8 ) 68 || ( atpb->atp_sreqto < 0 ) || (( atpb->atp_sreqtries < 1 ) 69 && ( atpb->atp_sreqtries != ATP_TRIES_INFINITE ))) { 70 errno = EINVAL; 71 return -1; 72 } 73 /* clean up any packet fragments left from last request 74 */ 75 for ( i = 0; i < 8; ++i ) { 76 if ( ah->atph_resppkt[ i ] != NULL ) { 77 atp_free_buf( ah->atph_resppkt[ i ] ); 78 ah->atph_resppkt[ i ] = NULL; 79 } 80 } 81 82 /* generate bitmap, tid and ctrlinfo 83 */ 84 atpb->atp_bitmap = ( 1 << respcount ) - 1; 85 86 /* allocate a new buffer and build request packet 87 */ 88 if (( req_buf = atp_alloc_buf()) == NULL ) { 89 return( -1 ); 90 } 91 atp_build_req_packet( req_buf, ah->atph_tid++, flags | ATP_TREQ, atpb ); 92 memcpy( &req_buf->atpbuf_addr, atpb->atp_saddr, 93 sizeof( struct sockaddr_at )); 94 95 /* send the initial request 96 */ 97#ifdef EBUG 98 printf( "\n<%d> atp_sreq: sending a %ld byte packet ", getpid(), 99 req_buf->atpbuf_dlen ); 100 atp_print_addr( " to", atpb->atp_saddr ); 101 putchar( '\n' ); 102 bprint( req_buf->atpbuf_info.atpbuf_data, req_buf->atpbuf_dlen ); 103#endif /* EBUG */ 104 105 gettimeofday( &ah->atph_reqtv, (struct timezone *)0 ); 106#ifdef DROPPACKETS 107if (( random() % 3 ) != 2 ) { 108#endif /* DROPPACKETS */ 109 if ( netddp_sendto( ah->atph_socket, req_buf->atpbuf_info.atpbuf_data, 110 req_buf->atpbuf_dlen, 0, (struct sockaddr *) atpb->atp_saddr, 111 sizeof( struct sockaddr_at )) != req_buf->atpbuf_dlen ) { 112 atp_free_buf( req_buf ); 113 return( -1 ); 114 } 115#ifdef DROPPACKETS 116} else printf( "<%d> atp_sreq: dropped request\n", getpid() ); 117#endif /* DROPPACKETS */ 118 119 if ( atpb->atp_sreqto != 0 ) { 120 if ( ah->atph_reqpkt != NULL ) { 121 atp_free_buf( ah->atph_reqpkt ); 122 } 123 ah->atph_reqto = atpb->atp_sreqto; 124 if ( atpb->atp_sreqtries == ATP_TRIES_INFINITE ) { 125 ah->atph_reqtries = ATP_TRIES_INFINITE; 126 } else { 127 /* we already sent one */ 128 ah->atph_reqtries = atpb->atp_sreqtries - 1; 129 } 130 ah->atph_reqpkt = req_buf; 131 ah->atph_rbitmap = ( 1 << respcount ) - 1; 132 ah->atph_rrespcount = respcount; 133 } else { 134 atp_free_buf( req_buf ); 135 ah->atph_rrespcount = 0; 136 } 137 138 return( 0 ); 139} 140