1/* 2 * $Id: atp_sresp.c,v 1.6 2009-10-13 22:55:37 didg 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 <errno.h> 34#include <sys/uio.h> 35#include <sys/time.h> 36#include <sys/socket.h> 37 38#include <netatalk/at.h> 39#include <netatalk/endian.h> 40 41#include <atalk/netddp.h> 42#include <atalk/atp.h> 43#include <atalk/util.h> 44 45#include "atp_internals.h" 46 47/* send a transaction response 48*/ 49int atp_sresp( 50 ATP ah, /* open atp handle */ 51 struct atp_block *atpb) /* parameter block */ 52{ 53 int i; 54 u_int8_t ctrlinfo; 55 struct atpbuf *resp_buf; 56 struct atpbuf *save_buf; /* uninitialized, OK 310105 */ 57 58#ifdef EBUG 59 atp_print_bufuse( ah, "atp_sresp" ); 60#endif /* EBUG */ 61 62 /* check parameters 63 */ 64 for ( i = atpb->atp_sresiovcnt - 1; i >= 0; --i ) { 65 if ( atpb->atp_sresiov[ i ].iov_len > ATP_MAXDATA ) 66 break; 67 } 68 if ( i >= 0 || atpb->atp_sresiovcnt < 1 || atpb->atp_sresiovcnt > 8 ) { 69 errno = EINVAL; 70 return -1; 71 } 72 73 /* allocate a new buffer for reponse packet construction 74 */ 75 if (( resp_buf = atp_alloc_buf()) == NULL ) { 76 return -1; 77 } 78 79 /* send all the response packets 80 * also need to attach list to ah for dup. detection (if XO) 81 */ 82#ifdef EBUG 83 printf( "<%d> preparing to send %s response tid=%hu ", getpid(), 84 ah->atph_rxo ? "XO" : "", ah->atph_rtid ); 85 atp_print_addr( " to", atpb->atp_saddr ); 86 putchar( '\n' ); 87#endif /* EBUG */ 88 if ( ah->atph_rxo ) { 89 if (( save_buf = atp_alloc_buf()) == NULL ) { 90 return -1; 91 } 92 for ( i = 0; i < 8; 93 save_buf->atpbuf_info.atpbuf_xo.atpxo_packet[ i++ ] = NULL ); 94 } 95 for ( i = 0; i < atpb->atp_sresiovcnt; ++i ) { 96 ctrlinfo = ATP_TRESP; 97#ifdef STS_RESPONSES 98 ctrlinfo |= ATP_STS; 99#endif /* STS_RESPONSES */ 100 if ( i == atpb->atp_sresiovcnt-1 ) { 101 ctrlinfo |= ATP_EOM; 102 } 103 atp_build_resp_packet( resp_buf, ah->atph_rtid, ctrlinfo, atpb, i ); 104 105 if ( ah->atph_rxo ) { 106 save_buf->atpbuf_info.atpbuf_xo.atpxo_packet[i] = resp_buf; 107 } 108#ifdef DROPPACKETS 109if (( random() % 3 ) != 2 ) { 110#endif /* DROPPACKETS */ 111#ifdef EBUG 112printf( "<%d> sending packet tid=%hu serial no.=%d\n", getpid(), 113 ah->atph_rtid, i ); 114bprint( resp_buf->atpbuf_info.atpbuf_data, resp_buf->atpbuf_dlen ); 115#endif /* EBUG */ 116 if ( netddp_sendto( ah->atph_socket, resp_buf->atpbuf_info.atpbuf_data, 117 resp_buf->atpbuf_dlen, 0, (struct sockaddr *) atpb->atp_saddr, 118 sizeof( struct sockaddr_at )) != resp_buf->atpbuf_dlen ) { 119 if ( ah->atph_rxo ) { 120 for ( ; i >= 0; --i ) { 121 atp_free_buf( save_buf->atpbuf_info.atpbuf_xo.atpxo_packet[ i ] ); 122 } 123 atp_free_buf( save_buf ); 124 } 125 return -1; 126 } 127#ifdef DROPPACKETS 128} else printf( "<%d> atp_sresp: dropped serial no. %d\n", getpid(), i ); 129#endif /* DROPPACKETS */ 130 /* allocate a buffer for next packet (if XO mode) 131 */ 132 if ( ah->atph_rxo && ( resp_buf = atp_alloc_buf()) == NULL ) { 133 return -1; 134 } 135 } 136 atp_free_buf( resp_buf ); 137 if ( ah->atph_rxo ) { 138 /* record timestamp, tid, release time, and destination address 139 */ 140 gettimeofday( &save_buf->atpbuf_info.atpbuf_xo.atpxo_tv, 141 (struct timezone *) 0 ); 142 save_buf->atpbuf_info.atpbuf_xo.atpxo_tid = ah->atph_rtid; 143 save_buf->atpbuf_info.atpbuf_xo.atpxo_reltime = ah->atph_rreltime; 144 memcpy( &save_buf->atpbuf_addr, atpb->atp_saddr, 145 sizeof( struct sockaddr_at )); 146 147 /* add to list of packets we have sent 148 */ 149 save_buf->atpbuf_next = ah->atph_sent; 150 ah->atph_sent = save_buf; 151#ifdef EBUG 152printf( "<%d> saved XO response\n", getpid()); 153#endif /* EBUG */ 154 } 155 return 0; 156} 157