5.5 smtpd_service函数(smtpd.c):smtp服务回调函数
2016-04-07 13:58
525 查看
我们先来看一下smtpd.c的主函数。其他各个业务模块的主函数结构和这里的main函数结构类似:
5572 从5572-5784的200多行均为参数初始化部分。以5573行为例,该行初始化了参数smtpd_soft_error_limit(VAR_SMTPD_SOFT_ERLIM),初始值为10(DEF_SMTPD_SOFT_ERLIM),将该初值记录在变量var_smtpd_soft_erlim中,取值范围为1到无穷。
5748 该main函数以single_server.c中的single_server_main为模板,回调函数为smtpd_service。
5785-5794 除了传入smtpd_service回调函数,业务模块还会向3.4中的模板传入其他函数执行,典型的如pre_jail_init,post_jail_init等,用来初始化变量。见4.4节。
下面我们来看回调函数smtpd_service
/smtpd/smtpd.c
5203 /*smtpd_service - service one client */
5204
5205 static voidsmtpd_service(VSTREAM *stream, char *service, char **argv)
5206 {
smtpd_service的stream参数,或者为网络流,或者为标准输入流,在single_server.c中已经设置好。
5220-5223 对于非stand-alone模式下的服务器,要确保可以得到当前支持的网络协议:
SMTPD_STAND_ALONE_STREAM宏定义如下:
inet_proto_info()返回3.2.7节的INET_PROTO_INFO结构体。
5234 使用smtpd_state_init函数初始化SMTPD_STATE结构体,大多数字段会被初始化为0,以下字段会被设置初值:
state->service= mystrdup(service);
设置服务名。
state->notify_mask= name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
var_notify_classes);
设置出错通知掩码位。
state->protocol =mystrdup(MAIL_PROTO_SMTP);
先初始化为smtp协议,在解析过程中可能会修改(见5.6.2)。
state->where= SMTPD_AFTER_CONNECT;
记录当前协议解析进行到哪一步,有如下选择:
smtpd_state_init函数中还运行了smtpd_peer_init函数确定客户端ip地址等信息(通过getpeername函数)。如果来自本地则初始化为“localhost”,取不到相关信息则初始化为“unknow”。这里我们远在HELO/EHLO命令解析函数执行前就通过网络函数取得客户端信息了,所以可以不考虑客户在HELO/EHLO命令中提供的客户信息——在helo_cmd和ehlo_cmd函数中没有相关获取客户端信息的代码。
5240-5244 在stand-alone模式下关闭TLS:既然不通过网络提供服务,当然也就不需要启动TLS。
5246-5256根据当前客户端主机名地址是否在smtpd_authorized_xclient_hosts或smtpd_authorized_xforward_hosts参数中设置xclient_allowed和xforward_allowed。这两个参数定义允许使用xclient和xforward命令的客户端主机名和地址。
5266-5267 无错情况下调用smtpd_proto函数进行smtp协议解析。该函数为smtp协议解析的主体。
/smtpd/smtpd.c 5570 int main(int argc, char **argv) 5571 { 5572 static const CONFIG_NINT_TABLE nint_table[] = { 5573 VAR_SMTPD_SOFT_ERLIM, DEF_SMTPD_SOFT_ERLIM, &var_smtpd_soft_erlim,1, 0, 5574 VAR_SMTPD_HARD_ERLIM, DEF_SMTPD_HARD_ERLIM, &var_smtpd_hard_erlim,1, 0, 5575 VAR_SMTPD_JUNK_CMD, DEF_SMTPD_JUNK_CMD, &var_smtpd_junk_cmd_limit,1, 0, 5576 VAR_VERIFY_POLL_COUNT, DEF_VERIFY_POLL_COUNT,&var_verify_poll_count, 1, 0, 5577 0, 5578 }; 5784 single_server_main(argc, argv, smtpd_service, 5785 CA_MAIL_SERVER_NINT_TABLE(nint_table), 5786 CA_MAIL_SERVER_INT_TABLE(int_table), 5787 CA_MAIL_SERVER_STR_TABLE(str_table), 5788 CA_MAIL_SERVER_RAW_TABLE(raw_table), 5789 CA_MAIL_SERVER_BOOL_TABLE(bool_table), 5790 CA_MAIL_SERVER_NBOOL_TABLE(nbool_table), 5791 CA_MAIL_SERVER_TIME_TABLE(time_table), 5792 CA_MAIL_SERVER_PRE_INIT(pre_jail_init), 5793 CA_MAIL_SERVER_PRE_ACCEPT(pre_accept), 5794 CA_MAIL_SERVER_POST_INIT(post_jail_init), 5795 0); 5796 }
5572 从5572-5784的200多行均为参数初始化部分。以5573行为例,该行初始化了参数smtpd_soft_error_limit(VAR_SMTPD_SOFT_ERLIM),初始值为10(DEF_SMTPD_SOFT_ERLIM),将该初值记录在变量var_smtpd_soft_erlim中,取值范围为1到无穷。
5748 该main函数以single_server.c中的single_server_main为模板,回调函数为smtpd_service。
5785-5794 除了传入smtpd_service回调函数,业务模块还会向3.4中的模板传入其他函数执行,典型的如pre_jail_init,post_jail_init等,用来初始化变量。见4.4节。
下面我们来看回调函数smtpd_service
/smtpd/smtpd.c
5203 /*smtpd_service - service one client */
5204
5205 static voidsmtpd_service(VSTREAM *stream, char *service, char **argv)
5206 {
smtpd_service的stream参数,或者为网络流,或者为标准输入流,在single_server.c中已经设置好。
5207 SMTPD_STATE state; 5208 5209 /* 5210 * Sanity check. This service takes nocommand-line arguments. 5211 */ 5212 if (argv[0]) 5213 msg_fatal("unexpectedcommand-line argument: %s", argv[0]); 5214 5215 /* 5216 * For sanity, require that at least oneof INET or INET6 is enabled. 5217 * Otherwise, we can't look up interfaceinformation, and we can't 5218 * convert names or addresses. 5219 */ 5220 if (SMTPD_STAND_ALONE_STREAM(stream) == 0 5221 &&inet_proto_info()->ai_family_list[0] == 0) 5222 msg_fatal("all network protocolsare disabled (%s = %s)", 5223 VAR_INET_PROTOCOLS,var_inet_protocols);
5220-5223 对于非stand-alone模式下的服务器,要确保可以得到当前支持的网络协议:
SMTPD_STAND_ALONE_STREAM宏定义如下:
/* *If running in stand-alone mode, do not try to talk to Postfix daemons but *write to queue file instead. */ #defineSMTPD_STAND_ALONE_STREAM(stream) \ (stream== VSTREAM_IN && getuid() != var_owner_uid)
inet_proto_info()返回3.2.7节的INET_PROTO_INFO结构体。
5224 5225 /* 5226 * This routine runs when a client hasconnected to our network port, or 5227 * when the smtp server is run instand-alone mode (input from pipe). 5228 * 5229 * Look up and sanitize the peer name,then initialize some connection- 5230 * specific state. When the name serviceis hosed, hostname lookup will 5231 * take a while. This is why I always runa local name server on critical 5232 * machines. 5233 */ 5234 smtpd_state_init(&state, stream,service);
5234 使用smtpd_state_init函数初始化SMTPD_STATE结构体,大多数字段会被初始化为0,以下字段会被设置初值:
state->service= mystrdup(service);
设置服务名。
state->notify_mask= name_mask(VAR_NOTIFY_CLASSES, mail_error_masks,
var_notify_classes);
设置出错通知掩码位。
state->protocol =mystrdup(MAIL_PROTO_SMTP);
先初始化为smtp协议,在解析过程中可能会修改(见5.6.2)。
state->where= SMTPD_AFTER_CONNECT;
记录当前协议解析进行到哪一步,有如下选择:
/* * Conversation stages. This is used for "lost connection afterXXX" *diagnostics. */ #defineSMTPD_AFTER_CONNECT "CONNECT" #defineSMTPD_AFTER_DATA "DATA content" #defineSMTPD_AFTER_DOT "END-OF-MESSAGE"
smtpd_state_init函数中还运行了smtpd_peer_init函数确定客户端ip地址等信息(通过getpeername函数)。如果来自本地则初始化为“localhost”,取不到相关信息则初始化为“unknow”。这里我们远在HELO/EHLO命令解析函数执行前就通过网络函数取得客户端信息了,所以可以不考虑客户在HELO/EHLO命令中提供的客户信息——在helo_cmd和ehlo_cmd函数中没有相关获取客户端信息的代码。
5235 msg_info("connect from %s",state.namaddr); 5236 5237 /* 5238 * Disable TLS when running in stand-alonemode via "sendmail -bs". 5239 */ 5240 if (SMTPD_STAND_ALONE((&state))) { 5241 var_smtpd_use_tls = 0; 5242 var_smtpd_enforce_tls = 0; 5243 var_smtpd_tls_auth_only = 0; 5244 }
5240-5244 在stand-alone模式下关闭TLS:既然不通过网络提供服务,当然也就不需要启动TLS。
5245 5246 /* 5247 * XCLIENT must not override its ownaccess control. 5248 */ 5249 xclient_allowed =SMTPD_STAND_ALONE((&state)) == 0 && 5250 namadr_list_match(xclient_hosts,state.name, state.addr); 5251 5252 /* 5253 * Overriding XFORWARD access controlmakes no sense, either. 5254 */ 5255 xforward_allowed =SMTPD_STAND_ALONE((&state)) == 0 && 5256 namadr_list_match(xforward_hosts,state.name, state.addr);
5246-5256根据当前客户端主机名地址是否在smtpd_authorized_xclient_hosts或smtpd_authorized_xforward_hosts参数中设置xclient_allowed和xforward_allowed。这两个参数定义允许使用xclient和xforward命令的客户端主机名和地址。
5257 5258 /* 5259 * See if we need to turn on verboselogging for this client. 5260 */ 5261 debug_peer_check(state.name, state.addr); 5262 5263 /* 5264 * Provide the SMTP service. 5265 */ 5266 if ((state.flags & SMTPD_FLAG_HANGUP)== 0) 5267 smtpd_proto(&state);
5266-5267 无错情况下调用smtpd_proto函数进行smtp协议解析。该函数为smtp协议解析的主体。
5268 5269 /* 5270 * After the client has gone away, cleanup whatever we have set up at 5271 * connection time. 5272 */ 5273 msg_info("disconnect from %s%s",state.namaddr, 5274 smtpd_format_cmd_stats(state.buffer)); 5275 smtpd_state_reset(&state); 5276 debug_peer_restore(); 5277 }
相关文章推荐
- IPC机制的几种通讯方式之ContentProvider
- 5.3.1.3 参数smtpd_delay_reject:延迟出错响应
- php获取一年中某一周的开始和结束时间
- $this->assign(); 与 $this->display(); PHP
- php计算字符串长度:utf8编码,包含中文
- php 根据指定的键对多维数组进行排序
- php本地文件包含&远程文件包含
- ThinkPHP 框架开发 零基础开发 网站商城 步骤 (2)
- PHP中PDO的事务处理分析
- wampServer 我进入phpadmin设置密码后。再访问就拒绝 error 1045
- 深入理解php底层:php生命周期
- PHP+Ajax实现无刷新分页实例详解(附demo源码下载)
- PHP的错误和异常处理
- PHP底层的运行机制与原理
- 最后一节php+mysql的故事
- 【未解决】php 中 '' "" null empty的区别
- thinkcmf thinkphp 学习
- 5.3.1.2 smtpd_check_*函数的ACL验证方法
- PHP 实现多服务器共享 SESSION 数据
- 浅谈PHP单引号和双引号的区别