bss_dgram.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:11k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /* crypto/bio/bio_dgram.c */
  2. /* 
  3.  * DTLS implementation written by Nagendra Modadugu
  4.  * (nagendra@cs.stanford.edu) for the OpenSSL project 2005.  
  5.  */
  6. /* ====================================================================
  7.  * Copyright (c) 1999-2005 The OpenSSL Project.  All rights reserved.
  8.  *
  9.  * Redistribution and use in source and binary forms, with or without
  10.  * modification, are permitted provided that the following conditions
  11.  * are met:
  12.  *
  13.  * 1. Redistributions of source code must retain the above copyright
  14.  *    notice, this list of conditions and the following disclaimer. 
  15.  *
  16.  * 2. Redistributions in binary form must reproduce the above copyright
  17.  *    notice, this list of conditions and the following disclaimer in
  18.  *    the documentation and/or other materials provided with the
  19.  *    distribution.
  20.  *
  21.  * 3. All advertising materials mentioning features or use of this
  22.  *    software must display the following acknowledgment:
  23.  *    "This product includes software developed by the OpenSSL Project
  24.  *    for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
  25.  *
  26.  * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
  27.  *    endorse or promote products derived from this software without
  28.  *    prior written permission. For written permission, please contact
  29.  *    openssl-core@OpenSSL.org.
  30.  *
  31.  * 5. Products derived from this software may not be called "OpenSSL"
  32.  *    nor may "OpenSSL" appear in their names without prior written
  33.  *    permission of the OpenSSL Project.
  34.  *
  35.  * 6. Redistributions of any form whatsoever must retain the following
  36.  *    acknowledgment:
  37.  *    "This product includes software developed by the OpenSSL Project
  38.  *    for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
  39.  *
  40.  * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
  41.  * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  42.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
  43.  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE OpenSSL PROJECT OR
  44.  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  45.  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  46.  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  47.  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  48.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  49.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  50.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
  51.  * OF THE POSSIBILITY OF SUCH DAMAGE.
  52.  * ====================================================================
  53.  *
  54.  * This product includes cryptographic software written by Eric Young
  55.  * (eay@cryptsoft.com).  This product includes software written by Tim
  56.  * Hudson (tjh@cryptsoft.com).
  57.  *
  58.  */
  59. #ifndef OPENSSL_NO_DGRAM
  60. #include <stdio.h>
  61. #include <errno.h>
  62. #define USE_SOCKETS
  63. #include "cryptlib.h"
  64. #include <openssl/bio.h>
  65. #define IP_MTU      14 /* linux is lame */
  66. #ifdef WATT32
  67. #define sock_write SockWrite  /* Watt-32 uses same names */
  68. #define sock_read  SockRead
  69. #define sock_puts  SockPuts
  70. #endif
  71. static int dgram_write(BIO *h, const char *buf, int num);
  72. static int dgram_read(BIO *h, char *buf, int size);
  73. static int dgram_puts(BIO *h, const char *str);
  74. static long dgram_ctrl(BIO *h, int cmd, long arg1, void *arg2);
  75. static int dgram_new(BIO *h);
  76. static int dgram_free(BIO *data);
  77. static int dgram_clear(BIO *bio);
  78. int BIO_dgram_should_retry(int s);
  79. static BIO_METHOD methods_dgramp=
  80. {
  81. BIO_TYPE_DGRAM,
  82. "datagram socket",
  83. dgram_write,
  84. dgram_read,
  85. dgram_puts,
  86. NULL, /* dgram_gets, */
  87. dgram_ctrl,
  88. dgram_new,
  89. dgram_free,
  90. NULL,
  91. };
  92. typedef struct bio_dgram_data_st
  93. {
  94. struct sockaddr peer;
  95. unsigned int connected;
  96. unsigned int _errno;
  97. unsigned int mtu;
  98. } bio_dgram_data;
  99. BIO_METHOD *BIO_s_datagram(void)
  100. {
  101. return(&methods_dgramp);
  102. }
  103. BIO *BIO_new_dgram(int fd, int close_flag)
  104. {
  105. BIO *ret;
  106. ret=BIO_new(BIO_s_datagram());
  107. if (ret == NULL) return(NULL);
  108. BIO_set_fd(ret,fd,close_flag);
  109. return(ret);
  110. }
  111. static int dgram_new(BIO *bi)
  112. {
  113. bio_dgram_data *data = NULL;
  114. bi->init=0;
  115. bi->num=0;
  116. data = OPENSSL_malloc(sizeof(bio_dgram_data));
  117. if (data == NULL)
  118. return 0;
  119. memset(data, 0x00, sizeof(bio_dgram_data));
  120.     bi->ptr = data;
  121. bi->flags=0;
  122. return(1);
  123. }
  124. static int dgram_free(BIO *a)
  125. {
  126. bio_dgram_data *data;
  127. if (a == NULL) return(0);
  128. if ( ! dgram_clear(a))
  129. return 0;
  130. data = (bio_dgram_data *)a->ptr;
  131. if(data != NULL) OPENSSL_free(data);
  132. return(1);
  133. }
  134. static int dgram_clear(BIO *a)
  135. {
  136. if (a == NULL) return(0);
  137. if (a->shutdown)
  138. {
  139. if (a->init)
  140. {
  141. SHUTDOWN2(a->num);
  142. }
  143. a->init=0;
  144. a->flags=0;
  145. }
  146. return(1);
  147. }
  148. static int dgram_read(BIO *b, char *out, int outl)
  149. {
  150. int ret=0;
  151. bio_dgram_data *data = (bio_dgram_data *)b->ptr;
  152. struct sockaddr peer;
  153. int peerlen = sizeof(peer);
  154. if (out != NULL)
  155. {
  156. clear_socket_error();
  157. memset(&peer, 0x00, peerlen);
  158. /* Last arg in recvfrom is signed on some platforms and
  159.  * unsigned on others. It is of type socklen_t on some
  160.  * but this is not universal. Cast to (void *) to avoid
  161.  * compiler warnings.
  162.  */
  163. ret=recvfrom(b->num,out,outl,0,&peer,(void *)&peerlen);
  164. if ( ! data->connected  && ret > 0)
  165. BIO_ctrl(b, BIO_CTRL_DGRAM_CONNECT, 0, &peer);
  166. BIO_clear_retry_flags(b);
  167. if (ret <= 0)
  168. {
  169. if (BIO_dgram_should_retry(ret))
  170. {
  171. BIO_set_retry_read(b);
  172. data->_errno = get_last_socket_error();
  173. }
  174. }
  175. }
  176. return(ret);
  177. }
  178. static int dgram_write(BIO *b, const char *in, int inl)
  179. {
  180. int ret;
  181. bio_dgram_data *data = (bio_dgram_data *)b->ptr;
  182. clear_socket_error();
  183.     if ( data->connected )
  184.         ret=send(b->num,in,inl,0);
  185.     else
  186.         ret=sendto(b->num, in, inl, 0, &data->peer, sizeof(data->peer));
  187. BIO_clear_retry_flags(b);
  188. if (ret <= 0)
  189. {
  190. if (BIO_sock_should_retry(ret))
  191. {
  192. BIO_set_retry_write(b);  
  193. data->_errno = get_last_socket_error();
  194. #if 0 /* higher layers are responsible for querying MTU, if necessary */
  195. if ( data->_errno == EMSGSIZE)
  196. /* retrieve the new MTU */
  197. BIO_ctrl(b, BIO_CTRL_DGRAM_QUERY_MTU, 0, NULL);
  198. #endif
  199. }
  200. }
  201. return(ret);
  202. }
  203. static long dgram_ctrl(BIO *b, int cmd, long num, void *ptr)
  204. {
  205. long ret=1;
  206. int *ip;
  207. struct sockaddr *to = NULL;
  208. bio_dgram_data *data = NULL;
  209. long sockopt_val = 0;
  210. unsigned int sockopt_len = 0;
  211. data = (bio_dgram_data *)b->ptr;
  212. switch (cmd)
  213. {
  214. case BIO_CTRL_RESET:
  215. num=0;
  216. case BIO_C_FILE_SEEK:
  217. ret=0;
  218. break;
  219. case BIO_C_FILE_TELL:
  220. case BIO_CTRL_INFO:
  221. ret=0;
  222. break;
  223. case BIO_C_SET_FD:
  224. dgram_clear(b);
  225. b->num= *((int *)ptr);
  226. b->shutdown=(int)num;
  227. b->init=1;
  228. break;
  229. case BIO_C_GET_FD:
  230. if (b->init)
  231. {
  232. ip=(int *)ptr;
  233. if (ip != NULL) *ip=b->num;
  234. ret=b->num;
  235. }
  236. else
  237. ret= -1;
  238. break;
  239. case BIO_CTRL_GET_CLOSE:
  240. ret=b->shutdown;
  241. break;
  242. case BIO_CTRL_SET_CLOSE:
  243. b->shutdown=(int)num;
  244. break;
  245. case BIO_CTRL_PENDING:
  246. case BIO_CTRL_WPENDING:
  247. ret=0;
  248. break;
  249. case BIO_CTRL_DUP:
  250. case BIO_CTRL_FLUSH:
  251. ret=1;
  252. break;
  253. case BIO_CTRL_DGRAM_CONNECT:
  254. to = (struct sockaddr *)ptr;
  255. #if 0
  256. if (connect(b->num, to, sizeof(struct sockaddr)) < 0)
  257. { perror("connect"); ret = 0; }
  258. else
  259. {
  260. #endif
  261. memcpy(&(data->peer),to, sizeof(struct sockaddr));
  262. #if 0
  263. }
  264. #endif
  265. break;
  266. /* (Linux)kernel sets DF bit on outgoing IP packets */
  267. #ifdef IP_MTU_DISCOVER
  268. case BIO_CTRL_DGRAM_MTU_DISCOVER:
  269. sockopt_val = IP_PMTUDISC_DO;
  270. if ((ret = setsockopt(b->num, IPPROTO_IP, IP_MTU_DISCOVER,
  271. &sockopt_val, sizeof(sockopt_val))) < 0)
  272. perror("setsockopt");
  273. break;
  274. #endif
  275. case BIO_CTRL_DGRAM_QUERY_MTU:
  276.          sockopt_len = sizeof(sockopt_val);
  277. if ((ret = getsockopt(b->num, IPPROTO_IP, IP_MTU, (void *)&sockopt_val,
  278. &sockopt_len)) < 0 || sockopt_val < 0)
  279. { ret = 0; }
  280. else
  281. {
  282. data->mtu = sockopt_val;
  283. ret = data->mtu;
  284. }
  285. break;
  286. case BIO_CTRL_DGRAM_GET_MTU:
  287. return data->mtu;
  288. break;
  289. case BIO_CTRL_DGRAM_SET_MTU:
  290. data->mtu = num;
  291. ret = num;
  292. break;
  293. case BIO_CTRL_DGRAM_SET_CONNECTED:
  294. to = (struct sockaddr *)ptr;
  295. if ( to != NULL)
  296. {
  297. data->connected = 1;
  298. memcpy(&(data->peer),to, sizeof(struct sockaddr));
  299. }
  300. else
  301. {
  302. data->connected = 0;
  303. memset(&(data->peer), 0x00, sizeof(struct sockaddr));
  304. }
  305. break;
  306.     case BIO_CTRL_DGRAM_SET_PEER:
  307.         to = (struct sockaddr *) ptr;
  308.         memcpy(&(data->peer), to, sizeof(struct sockaddr));
  309.         break;
  310. case BIO_CTRL_DGRAM_SET_RECV_TIMEOUT:
  311. if ( setsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, ptr,
  312. sizeof(struct timeval)) < 0)
  313. { perror("setsockopt"); ret = -1; }
  314. break;
  315. case BIO_CTRL_DGRAM_GET_RECV_TIMEOUT:
  316. if ( getsockopt(b->num, SOL_SOCKET, SO_RCVTIMEO, 
  317. ptr, (void *)&ret) < 0)
  318. { perror("getsockopt"); ret = -1; }
  319. break;
  320. case BIO_CTRL_DGRAM_SET_SEND_TIMEOUT:
  321. if ( setsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, ptr,
  322. sizeof(struct timeval)) < 0)
  323. { perror("setsockopt"); ret = -1; }
  324. break;
  325. case BIO_CTRL_DGRAM_GET_SEND_TIMEOUT:
  326. if ( getsockopt(b->num, SOL_SOCKET, SO_SNDTIMEO, 
  327. ptr, (void *)&ret) < 0)
  328. { perror("getsockopt"); ret = -1; }
  329. break;
  330. case BIO_CTRL_DGRAM_GET_SEND_TIMER_EXP:
  331. /* fall-through */
  332. case BIO_CTRL_DGRAM_GET_RECV_TIMER_EXP:
  333. if ( data->_errno == EAGAIN)
  334. {
  335. ret = 1;
  336. data->_errno = 0;
  337. }
  338. else
  339. ret = 0;
  340. break;
  341. #ifdef EMSGSIZE
  342. case BIO_CTRL_DGRAM_MTU_EXCEEDED:
  343. if ( data->_errno == EMSGSIZE)
  344. {
  345. ret = 1;
  346. data->_errno = 0;
  347. }
  348. else
  349. ret = 0;
  350. break;
  351. #endif
  352. default:
  353. ret=0;
  354. break;
  355. }
  356. return(ret);
  357. }
  358. static int dgram_puts(BIO *bp, const char *str)
  359. {
  360. int n,ret;
  361. n=strlen(str);
  362. ret=dgram_write(bp,str,n);
  363. return(ret);
  364. }
  365. int BIO_dgram_should_retry(int i)
  366. {
  367. int err;
  368. if ((i == 0) || (i == -1))
  369. {
  370. err=get_last_socket_error();
  371. #if defined(OPENSSL_SYS_WINDOWS) && 0 /* more microsoft stupidity? perhaps not? Ben 4/1/99 */
  372. if ((i == -1) && (err == 0))
  373. return(1);
  374. #endif
  375. return(BIO_dgram_non_fatal_error(err));
  376. }
  377. return(0);
  378. }
  379. int BIO_dgram_non_fatal_error(int err)
  380. {
  381. switch (err)
  382. {
  383. #if defined(OPENSSL_SYS_WINDOWS)
  384. # if defined(WSAEWOULDBLOCK)
  385. case WSAEWOULDBLOCK:
  386. # endif
  387. # if 0 /* This appears to always be an error */
  388. #  if defined(WSAENOTCONN)
  389. case WSAENOTCONN:
  390. #  endif
  391. # endif
  392. #endif
  393. #ifdef EWOULDBLOCK
  394. # ifdef WSAEWOULDBLOCK
  395. #  if WSAEWOULDBLOCK != EWOULDBLOCK
  396. case EWOULDBLOCK:
  397. #  endif
  398. # else
  399. case EWOULDBLOCK:
  400. # endif
  401. #endif
  402. #if defined(ENOTCONN)
  403. case ENOTCONN:
  404. #endif
  405. #ifdef EINTR
  406. case EINTR:
  407. #endif
  408. #ifdef EAGAIN
  409. #if EWOULDBLOCK != EAGAIN
  410. case EAGAIN:
  411. # endif
  412. #endif
  413. #ifdef EPROTO
  414. case EPROTO:
  415. #endif
  416. #ifdef EINPROGRESS
  417. case EINPROGRESS:
  418. #endif
  419. #ifdef EALREADY
  420. case EALREADY:
  421. #endif
  422. /* DF bit set, and packet larger than MTU */
  423. #ifdef EMSGSIZE
  424. case EMSGSIZE:
  425. #endif
  426. return(1);
  427. /* break; */
  428. default:
  429. break;
  430. }
  431. return(0);
  432. }
  433. #endif