Print this page
First attempt at further IPsec cluster cleanup


1070         }
1071         if (isrcext != NULL && idstext == NULL) {
1072                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST;
1073                 return (EINVAL);
1074         }
1075         if (assoc == NULL) {
1076                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
1077                 return (EINVAL);
1078         }
1079         if (key == NULL) {
1080                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_AKEY;
1081                 return (EINVAL);
1082         }
1083 
1084         src = (struct sockaddr_in *)(srcext + 1);
1085         dst = (struct sockaddr_in *)(dstext + 1);
1086 
1087         /* Sundry ADD-specific reality checks. */
1088         /* XXX STATS : Logging/stats here? */
1089 
1090         if ((assoc->sadb_sa_state != SADB_SASTATE_MATURE) &&
1091             (assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE_ELSEWHERE)) {
1092                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
1093                 return (EINVAL);
1094         }
1095         if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
1096                 *diagnostic = SADB_X_DIAGNOSTIC_ENCR_NOTSUPP;
1097                 return (EINVAL);
1098         }
1099         if (assoc->sadb_sa_flags & ~ahstack->ah_sadb.s_addflags) {
1100                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
1101                 return (EINVAL);
1102         }
1103         if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0)
1104                 return (EINVAL);
1105 
1106         ASSERT(src->sin_family == dst->sin_family);
1107 
1108         /* Stuff I don't support, for now.  XXX Diagnostic? */
1109         if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1110                 return (EOPNOTSUPP);
1111 


1149                 mutex_exit(&ipss->ipsec_alg_lock);
1150                 return (EINVAL);
1151         }
1152 
1153         mutex_exit(&ipss->ipsec_alg_lock);
1154 
1155         return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1156             diagnostic, ahstack));
1157 }
1158 
1159 /* Refactor me */
1160 /*
1161  * Update a security association.  Updates come in two varieties.  The first
1162  * is an update of lifetimes on a non-larval SA.  The second is an update of
1163  * a larval SA, which ends up looking a lot more like an add.
1164  */
1165 static int
1166 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1167     ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1168 {
1169         sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1170         sadb_address_t *dstext =
1171             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1172         mblk_t  *buf_pkt;
1173         int rcode;
1174 
1175         if (dstext == NULL) {
1176                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
1177                 return (EINVAL);
1178         }
1179 
1180         rcode = sadb_update_sa(mp, ksi, &buf_pkt, &ahstack->ah_sadb,
1181             diagnostic, ahstack->ah_pfkey_q, ah_add_sa,
1182             ahstack->ipsecah_netstack, sadb_msg_type);
1183 
1184         if ((assoc->sadb_sa_state != SADB_X_SASTATE_ACTIVE) ||
1185             (rcode != 0)) {
1186                 return (rcode);
1187         }
1188 
1189         HANDLE_BUF_PKT(ah_taskq, ahstack->ipsecah_netstack->netstack_ipsec,
1190             ahstack->ah_dropper, buf_pkt);
1191 
1192         return (rcode);
1193 }
1194 
1195 /* Refactor me */
1196 /*
1197  * Delete a security association.  This is REALLY likely to be code common to
1198  * both AH and ESP.  Find the association, then unlink it.
1199  */
1200 static int
1201 ah_del_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1202     ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1203 {
1204         sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1205         sadb_address_t *dstext =
1206             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1207         sadb_address_t *srcext =
1208             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
1209         struct sockaddr_in *sin;
1210 
1211         if (assoc == NULL) {
1212                 if (dstext != NULL)


1319          * AF_INET.
1320          */
1321         if (!sadb_addrfix(ksi, ahstack->ah_pfkey_q, mp,
1322             ahstack->ipsecah_netstack) ||
1323             ah_pfkey_reality_failures(mp, ksi, ahstack)) {
1324                 return;
1325         }
1326 
1327         switch (samsg->sadb_msg_type) {
1328         case SADB_ADD:
1329                 error = ah_add_sa(mp, ksi, &diagnostic,
1330                     ahstack->ipsecah_netstack);
1331                 if (error != 0) {
1332                         sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1333                             diagnostic, ksi->ks_in_serial);
1334                 }
1335                 /* else ah_add_sa() took care of things. */
1336                 break;
1337         case SADB_DELETE:
1338         case SADB_X_DELPAIR:
1339         case SADB_X_DELPAIR_STATE:
1340                 error = ah_del_sa(mp, ksi, &diagnostic, ahstack,
1341                     samsg->sadb_msg_type);
1342                 if (error != 0) {
1343                         sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1344                             diagnostic, ksi->ks_in_serial);
1345                 }
1346                 /* Else ah_del_sa() took care of things. */
1347                 break;
1348         case SADB_GET:
1349                 error = sadb_delget_sa(mp, ksi, &ahstack->ah_sadb, &diagnostic,
1350                     ahstack->ah_pfkey_q, samsg->sadb_msg_type);
1351                 if (error != 0) {
1352                         sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1353                             diagnostic, ksi->ks_in_serial);
1354                 }
1355                 /* Else sadb_get_sa() took care of things. */
1356                 break;
1357         case SADB_FLUSH:
1358                 sadbp_flush(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
1359                 sadb_pfkey_echo(ahstack->ah_pfkey_q, mp, samsg, ksi, NULL);


1893 
1894 /* Refactor me */
1895 /*
1896  * Handle the SADB_GETSPI message.  Create a larval SA.
1897  */
1898 static void
1899 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1900 {
1901         ipsa_t *newbie, *target;
1902         isaf_t *outbound, *inbound;
1903         int rc, diagnostic;
1904         sadb_sa_t *assoc;
1905         keysock_out_t *kso;
1906         uint32_t newspi;
1907 
1908         /*
1909          * Randomly generate a proposed SPI value.
1910          */
1911         (void) random_get_pseudo_bytes((uint8_t *)&newspi, sizeof (uint32_t));
1912         newbie = sadb_getspi(ksi, newspi, &diagnostic,
1913             ahstack->ipsecah_netstack, IPPROTO_AH);
1914 
1915         if (newbie == NULL) {
1916                 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, ENOMEM, diagnostic,
1917                     ksi->ks_in_serial);
1918                 return;
1919         } else if (newbie == (ipsa_t *)-1) {
1920                 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EINVAL, diagnostic,
1921                     ksi->ks_in_serial);
1922                 return;
1923         }
1924 
1925         /*
1926          * XXX - We may randomly collide.  We really should recover from this.
1927          *       Unfortunately, that could require spending way-too-much-time
1928          *       in here.  For now, let the user retry.
1929          */
1930 
1931         if (newbie->ipsa_addrfam == AF_INET6) {
1932                 outbound = OUTBOUND_BUCKET_V6(&ahstack->ah_sadb.s_v6,
1933                     *(uint32_t *)(newbie->ipsa_dstaddr));


3817                         *dest32 = *(dest32 - (newpos >> 2));
3818         } else {
3819                 dest = mp->b_rptr + ah_offset;
3820                 while (--dest >= mp->b_rptr)
3821                         *dest = *(dest - newpos);
3822         }
3823         freeb(phdr_mp);
3824 
3825         /*
3826          * If SA is labelled, use its label, else inherit the label
3827          */
3828         if (is_system_labeled() && (assoc->ipsa_tsl != NULL)) {
3829                 if (!ip_recv_attr_replace_label(ira, assoc->ipsa_tsl)) {
3830                         ip_drop_packet(mp, B_TRUE, ira->ira_ill,
3831                             DROPPER(ipss, ipds_ah_nomem), &ahstack->ah_dropper);
3832                         BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3833                         return (NULL);
3834                 }
3835         }
3836 
3837         if (assoc->ipsa_state == IPSA_STATE_IDLE) {
3838                 /*
3839                  * Cluster buffering case.  Tell caller that we're
3840                  * handling the packet.
3841                  */
3842                 sadb_buf_pkt(assoc, mp, ira);
3843                 return (NULL);
3844         }
3845 
3846         return (mp);
3847 
3848 ah_in_discard:
3849         IP_AH_BUMP_STAT(ipss, in_discards);
3850         ip_drop_packet(phdr_mp, B_TRUE, ira->ira_ill, counter,
3851             &ahstack->ah_dropper);
3852         BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3853         return (NULL);
3854 }
3855 
3856 /*
3857  * Invoked after processing of an outbound packet by the
3858  * kernel crypto framework, either by ah_submit_req() for a request
3859  * executed syncrhonously, or by the KEF callback for a request
3860  * executed asynchronously.
3861  */
3862 static mblk_t *
3863 ah_auth_out_done(mblk_t *phdr_mp, ip_xmit_attr_t *ixa, ipsec_crypto_t *ic)
3864 {
3865         mblk_t *mp;




1070         }
1071         if (isrcext != NULL && idstext == NULL) {
1072                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_INNER_DST;
1073                 return (EINVAL);
1074         }
1075         if (assoc == NULL) {
1076                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_SA;
1077                 return (EINVAL);
1078         }
1079         if (key == NULL) {
1080                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_AKEY;
1081                 return (EINVAL);
1082         }
1083 
1084         src = (struct sockaddr_in *)(srcext + 1);
1085         dst = (struct sockaddr_in *)(dstext + 1);
1086 
1087         /* Sundry ADD-specific reality checks. */
1088         /* XXX STATS : Logging/stats here? */
1089 
1090         if (assoc->sadb_sa_state != SADB_SASTATE_MATURE) {

1091                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SASTATE;
1092                 return (EINVAL);
1093         }
1094         if (assoc->sadb_sa_encrypt != SADB_EALG_NONE) {
1095                 *diagnostic = SADB_X_DIAGNOSTIC_ENCR_NOTSUPP;
1096                 return (EINVAL);
1097         }
1098         if (assoc->sadb_sa_flags & ~ahstack->ah_sadb.s_addflags) {
1099                 *diagnostic = SADB_X_DIAGNOSTIC_BAD_SAFLAGS;
1100                 return (EINVAL);
1101         }
1102         if ((*diagnostic = sadb_hardsoftchk(hard, soft, idle)) != 0)
1103                 return (EINVAL);
1104 
1105         ASSERT(src->sin_family == dst->sin_family);
1106 
1107         /* Stuff I don't support, for now.  XXX Diagnostic? */
1108         if (ksi->ks_in_extv[SADB_EXT_LIFETIME_CURRENT] != NULL)
1109                 return (EOPNOTSUPP);
1110 


1148                 mutex_exit(&ipss->ipsec_alg_lock);
1149                 return (EINVAL);
1150         }
1151 
1152         mutex_exit(&ipss->ipsec_alg_lock);
1153 
1154         return (ah_add_sa_finish(mp, (sadb_msg_t *)mp->b_cont->b_rptr, ksi,
1155             diagnostic, ahstack));
1156 }
1157 
1158 /* Refactor me */
1159 /*
1160  * Update a security association.  Updates come in two varieties.  The first
1161  * is an update of lifetimes on a non-larval SA.  The second is an update of
1162  * a larval SA, which ends up looking a lot more like an add.
1163  */
1164 static int
1165 ah_update_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1166     ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1167 {

1168         sadb_address_t *dstext =
1169             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];


1170 
1171         if (dstext == NULL) {
1172                 *diagnostic = SADB_X_DIAGNOSTIC_MISSING_DST;
1173                 return (EINVAL);
1174         }
1175 
1176         return (sadb_update_sa(mp, ksi, &ahstack->ah_sadb, diagnostic,
1177             ahstack->ah_pfkey_q, ah_add_sa, ahstack->ipsecah_netstack,
1178             sadb_msg_type));










1179 }
1180 
1181 /* Refactor me */
1182 /*
1183  * Delete a security association.  This is REALLY likely to be code common to
1184  * both AH and ESP.  Find the association, then unlink it.
1185  */
1186 static int
1187 ah_del_sa(mblk_t *mp, keysock_in_t *ksi, int *diagnostic,
1188     ipsecah_stack_t *ahstack, uint8_t sadb_msg_type)
1189 {
1190         sadb_sa_t *assoc = (sadb_sa_t *)ksi->ks_in_extv[SADB_EXT_SA];
1191         sadb_address_t *dstext =
1192             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_DST];
1193         sadb_address_t *srcext =
1194             (sadb_address_t *)ksi->ks_in_extv[SADB_EXT_ADDRESS_SRC];
1195         struct sockaddr_in *sin;
1196 
1197         if (assoc == NULL) {
1198                 if (dstext != NULL)


1305          * AF_INET.
1306          */
1307         if (!sadb_addrfix(ksi, ahstack->ah_pfkey_q, mp,
1308             ahstack->ipsecah_netstack) ||
1309             ah_pfkey_reality_failures(mp, ksi, ahstack)) {
1310                 return;
1311         }
1312 
1313         switch (samsg->sadb_msg_type) {
1314         case SADB_ADD:
1315                 error = ah_add_sa(mp, ksi, &diagnostic,
1316                     ahstack->ipsecah_netstack);
1317                 if (error != 0) {
1318                         sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1319                             diagnostic, ksi->ks_in_serial);
1320                 }
1321                 /* else ah_add_sa() took care of things. */
1322                 break;
1323         case SADB_DELETE:
1324         case SADB_X_DELPAIR:

1325                 error = ah_del_sa(mp, ksi, &diagnostic, ahstack,
1326                     samsg->sadb_msg_type);
1327                 if (error != 0) {
1328                         sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1329                             diagnostic, ksi->ks_in_serial);
1330                 }
1331                 /* Else ah_del_sa() took care of things. */
1332                 break;
1333         case SADB_GET:
1334                 error = sadb_delget_sa(mp, ksi, &ahstack->ah_sadb, &diagnostic,
1335                     ahstack->ah_pfkey_q, samsg->sadb_msg_type);
1336                 if (error != 0) {
1337                         sadb_pfkey_error(ahstack->ah_pfkey_q, mp, error,
1338                             diagnostic, ksi->ks_in_serial);
1339                 }
1340                 /* Else sadb_get_sa() took care of things. */
1341                 break;
1342         case SADB_FLUSH:
1343                 sadbp_flush(&ahstack->ah_sadb, ahstack->ipsecah_netstack);
1344                 sadb_pfkey_echo(ahstack->ah_pfkey_q, mp, samsg, ksi, NULL);


1878 
1879 /* Refactor me */
1880 /*
1881  * Handle the SADB_GETSPI message.  Create a larval SA.
1882  */
1883 static void
1884 ah_getspi(mblk_t *mp, keysock_in_t *ksi, ipsecah_stack_t *ahstack)
1885 {
1886         ipsa_t *newbie, *target;
1887         isaf_t *outbound, *inbound;
1888         int rc, diagnostic;
1889         sadb_sa_t *assoc;
1890         keysock_out_t *kso;
1891         uint32_t newspi;
1892 
1893         /*
1894          * Randomly generate a proposed SPI value.
1895          */
1896         (void) random_get_pseudo_bytes((uint8_t *)&newspi, sizeof (uint32_t));
1897         newbie = sadb_getspi(ksi, newspi, &diagnostic,
1898             ahstack->ipsecah_netstack);
1899 
1900         if (newbie == NULL) {
1901                 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, ENOMEM, diagnostic,
1902                     ksi->ks_in_serial);
1903                 return;
1904         } else if (newbie == (ipsa_t *)-1) {
1905                 sadb_pfkey_error(ahstack->ah_pfkey_q, mp, EINVAL, diagnostic,
1906                     ksi->ks_in_serial);
1907                 return;
1908         }
1909 
1910         /*
1911          * XXX - We may randomly collide.  We really should recover from this.
1912          *       Unfortunately, that could require spending way-too-much-time
1913          *       in here.  For now, let the user retry.
1914          */
1915 
1916         if (newbie->ipsa_addrfam == AF_INET6) {
1917                 outbound = OUTBOUND_BUCKET_V6(&ahstack->ah_sadb.s_v6,
1918                     *(uint32_t *)(newbie->ipsa_dstaddr));


3802                         *dest32 = *(dest32 - (newpos >> 2));
3803         } else {
3804                 dest = mp->b_rptr + ah_offset;
3805                 while (--dest >= mp->b_rptr)
3806                         *dest = *(dest - newpos);
3807         }
3808         freeb(phdr_mp);
3809 
3810         /*
3811          * If SA is labelled, use its label, else inherit the label
3812          */
3813         if (is_system_labeled() && (assoc->ipsa_tsl != NULL)) {
3814                 if (!ip_recv_attr_replace_label(ira, assoc->ipsa_tsl)) {
3815                         ip_drop_packet(mp, B_TRUE, ira->ira_ill,
3816                             DROPPER(ipss, ipds_ah_nomem), &ahstack->ah_dropper);
3817                         BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3818                         return (NULL);
3819                 }
3820         }
3821 









3822         return (mp);
3823 
3824 ah_in_discard:
3825         IP_AH_BUMP_STAT(ipss, in_discards);
3826         ip_drop_packet(phdr_mp, B_TRUE, ira->ira_ill, counter,
3827             &ahstack->ah_dropper);
3828         BUMP_MIB(ira->ira_ill->ill_ip_mib, ipIfStatsInDiscards);
3829         return (NULL);
3830 }
3831 
3832 /*
3833  * Invoked after processing of an outbound packet by the
3834  * kernel crypto framework, either by ah_submit_req() for a request
3835  * executed syncrhonously, or by the KEF callback for a request
3836  * executed asynchronously.
3837  */
3838 static mblk_t *
3839 ah_auth_out_done(mblk_t *phdr_mp, ip_xmit_attr_t *ixa, ipsec_crypto_t *ic)
3840 {
3841         mblk_t *mp;